Eine Aufzählung basierend auf Werten in einer Datenbank-Nachschlagetabelle automatisch erstellen?

116

Wie erstelle ich automatisch eine Aufzählung und verwende anschließend ihre Werte in C # basierend auf Werten in einer Datenbank-Nachschlagetabelle (unter Verwendung der Datenschicht der Unternehmensbibliothek)?

Wenn ich beispielsweise einen neuen Suchwert in die Datenbank einfüge, möchte ich die zusätzliche statische Aufzählungswertdeklaration nicht manuell im Code hinzufügen müssen. Ich möchte die Aufzählung mit der Datenbank synchron halten.

Gibt es so etwas?


Ich möchte nicht einen Code erzeugte statische Enum (per erstellen The Code Project Artikel Enum - Code - Generator - Generieren von ENUM - Code automatisch aus der Datenbank Nachschlagetabellen ) und würde es vorziehen , sie vollautomatisch zu sein.

billfredtom
quelle
Wäre es möglich, dass Sie versuchen, eine Aufzählung so zu verwenden, dass es eine bessere Lösung gibt?
Dan
Ich bin bei @Dan, es muss einen besseren Weg geben, dies zu tun.
N_A
@mydogisbox was ist der bessere Weg?
eran otzap
@eranotzer Eigentlich wäre es nach einigem Nachdenken ziemlich einfach, einen vorgefertigten Schritt zu schreiben, der die
Datenbank
1
Davon abgesehen bin ich mir nicht sicher, was er mit "Ich möchte keine durch Code generierte statische Aufzählung erstellen" meint. Vielleicht passt dies nicht zu den Anforderungen.
N_A

Antworten:

97

Ich mache genau das, aber Sie müssen eine Art Codegenerierung durchführen, damit dies funktioniert.

In meiner Lösung habe ich ein Projekt "EnumeratedTypes" hinzugefügt. Dies ist eine Konsolenanwendung, die alle Werte aus der Datenbank abruft und die Aufzählungen daraus erstellt. Anschließend werden alle Aufzählungen in einer Assembly gespeichert.

Der Enum-Generierungscode lautet wie folgt:

// Get the current application domain for the current thread
AppDomain currentDomain = AppDomain.CurrentDomain;

// Create a dynamic assembly in the current application domain,
// and allow it to be executed and saved to disk.
AssemblyName name = new AssemblyName("MyEnums");
AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(name,
                                      AssemblyBuilderAccess.RunAndSave);

// Define a dynamic module in "MyEnums" assembly.
// For a single-module assembly, the module has the same name as the assembly.
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name,
                                  name.Name + ".dll");

// Define a public enumeration with the name "MyEnum" and an underlying type of Integer.
EnumBuilder myEnum = moduleBuilder.DefineEnum("EnumeratedTypes.MyEnum",
                         TypeAttributes.Public, typeof(int));

// Get data from database
MyDataAdapter someAdapter = new MyDataAdapter();
MyDataSet.MyDataTable myData = myDataAdapter.GetMyData();

foreach (MyDataSet.MyDataRow row in myData.Rows)
{
    myEnum.DefineLiteral(row.Name, row.Key);
}

// Create the enum
myEnum.CreateType();

// Finally, save the assembly
assemblyBuilder.Save(name.Name + ".dll");

Meine anderen Projekte in der Lösung verweisen auf diese generierte Baugruppe. Infolgedessen kann ich dann die dynamischen Aufzählungen im Code zusammen mit Intellisense verwenden.

Dann habe ich ein Post-Build-Ereignis hinzugefügt, damit dieses "EnumeratedTypes" -Projekt nach dem Erstellen selbst ausgeführt wird und die Datei "MyEnums.dll" generiert.

Übrigens ist es hilfreich, die Erstellungsreihenfolge Ihres Projekts so zu ändern , dass zuerst "EnumeratedTypes" erstellt wird. Andernfalls können Sie, sobald Sie Ihre dynamisch generierte DLL verwenden, keinen Build mehr erstellen, wenn die DLL jemals gelöscht wird. (Henne-Ei-Problem - Ihre anderen Projekte in der Lösung benötigen diese DLL, um ordnungsgemäß zu erstellen, und Sie können die DLL erst erstellen, wenn Sie Ihre Lösung erstellt haben ...)

Ich habe den größten Teil des obigen Codes aus diesem MSDN-Artikel erhalten .

Hoffe das hilft!

Pandincus
quelle
7
Für diejenigen, die nicht wissen, wie die resultierende ausführbare Datei nach dem Erstellen ausgeführt wird: 1) Klicken Sie mit der rechten Maustaste auf das Projekt. 2) Klicken Sie auf Eigenschaften. 3) Klicken Sie auf Ereignisse erstellen. 4) Geben Sie im Textfeld "Befehlszeilen für Ereignisse nach dem Erstellen" ein $ (TargetPath)
Miguel
Ist es möglich, Dynamic Enum mit einer benutzerdefinierten Attributdefinition durchzuführen, wie in diesem Link erwähnt ?
Balagurunathan Marimuthu
49

Aufzählungen müssen zur Kompilierungszeit angegeben werden, Sie können zur Laufzeit keine Aufzählungen dynamisch hinzufügen - und warum sollten Sie, es würde keine Verwendung / Referenz im Code geben?

Aus Professional C # 2008:

Die wahre Stärke von Aufzählungen in C # besteht darin, dass sie hinter den Kulissen als Strukturen instanziiert werden, die von der Basisklasse System.Enum abgeleitet sind. Dies bedeutet, dass es möglich ist, Methoden gegen sie aufzurufen, um einige nützliche Aufgaben auszuführen. Beachten Sie, dass aufgrund der Art und Weise, wie .NET Framework implementiert ist, kein Leistungsverlust mit der syntaktischen Behandlung der Aufzählungen als Strukturen verbunden ist. In der Praxis existieren Aufzählungen nach dem Kompilieren Ihres Codes wie int und float als primitive Typen.

Ich bin mir also nicht sicher, ob Sie Enums so verwenden können, wie Sie es möchten.

Marcus L.
quelle
1
Ich bin mir nicht sicher, was Billfredtoms Argumentation ist, aber meine war, dass ich es vermeiden konnte, manuelle String-Lookups für bestimmte Schlüssel durchzuführen, anstatt sie in meinen Code zu integrieren. Ich bevorzuge es einfach, Logik für stark typisierte Werte anstelle von schwachen Zeichenfolgen ausführen zu können. Eine Einschränkung wäre, dass, da wir jetzt Code haben, der auf einer dynamisch generierten Aufzählung basiert, wenn wir den Wert aus der Datenbank löschen, das nächste Mal, wenn wir versuchen, unseren Code zu kompilieren, dieser fehlschlägt.
Pandincus
14
Poster und 18 Upvotes haben seinen Standpunkt irgendwie verfehlt. Es hört sich so an, als ob er generierte Aufzählungen möchte , keine dynamischen Laufzeitaufzählungen.
Matt Mitchell
+1. Eine Aufzählung ist im Grunde nur eine andere Möglichkeit, ganzzahlige Konstanten zu definieren (auch wenn sie System.Enumüber zusätzliche Funktionen verfügt). Anstatt zu schreiben const int Red=0, Green=1, Blue=3;, schreibst du enum { Red, Green, Blue }. Eine Konstante ist per Definition konstant und nicht dynamisch.
Olivier Jacot-Descombes
2
@Oliver Wenn Sie über Semantik streiten wollen, sind Sie richtig. Aber ich stimme dem Kommentar von Graphain zu - ich glaube, das OP sucht nach generierten Aufzählungen. Er möchte, dass die Aufzählungswerte aus der Datenbank stammen und nicht hart codiert werden müssen.
Pandincus
1
Oder ... Nehmen wir an, ich erlaube jemandem in meiner web.config, Tokentypen für E-Mail-Vorlagen für meinen E-Mail-Vorlagencode zu definieren. Es wäre schön, wenn meine vorhandene Enumeration namens EmailTokens, die diese Zeichenfolgentypen darstellt, basierend auf den in meiner web.config definierten Typen generiert würde. Wenn also jemand über meinen Schlüsselwert, z. B. "E-Mail, FName", ein neues E-Mail-Token in die Webkonfiguration einfügt und ich bereits eine Aufzählung habe, mit der ich diese Token wie EmailTemplate.Email darstellen werde, wäre es schön, wenn jemand dies einfach könnte Fügen Sie ein neues String-Token in diesen Schlüssel in der web.config ein und meine Aufzählung würde automatisch die const
PositiveGuy
18

Muss es eine tatsächliche Aufzählung sein? Wie wäre es Dictionary<string,int>stattdessen mit einem ?

beispielsweise

Dictionary<string, int> MyEnum = new Dictionary(){{"One", 1}, {"Two", 2}};
Console.WriteLine(MyEnum["One"]);
Autodidakt
quelle
11
Ich würde nicht versuchen, es so zu machen. Sie verlieren Ihre Überprüfungen der Kompilierungszeit und sind anfällig für Tippfehler. Alle Vorteile von Aufzählungen sind weg. Sie könnten String-Konstanten einführen, aber dann sind Sie wieder da, wo Sie begonnen haben.
Daniel Brückner
1
Genau. Denken Sie jedoch daran, dass falsch eingegebene Zeichenfolgen zur Laufzeit abgefangen werden. Fügen Sie einfach einen Testfall hinzu, um alle Mitglieder der Aufzählung abzudecken.
Autodidakt
1
Tippfehler sind kein Problem, wenn Sie Konstanten anstelle von Literalen verwenden
Maslow
@Maslow Angenommen, Sie meinen Aufzählungen, keine Zeichenfolgenkonstanten.
Matt Mitchell
4
+1. Die Verwendung eines Wörterbuchs oder eines HashSets kommt einer möglicherweise dynamischen Aufzählung am nächsten. Volldynamisch bedeutet, dass dies zur Laufzeit geschieht und daher zur Laufzeit eine Fehlerprüfung durchgeführt werden muss.
Olivier Jacot-Descombes
13

Ich habe dies mit einer T4- Vorlage gemacht. Es ist ziemlich trivial, eine .tt-Datei in Ihr Projekt einzufügen und Visual Studio so einzurichten, dass die T4-Vorlage als Vorerstellungsschritt ausgeführt wird.

Der T4 generiert eine CS-Datei. Dies bedeutet, dass Sie einfach die Datenbank abfragen und aus dem Ergebnis eine Aufzählung in einer CS-Datei erstellen können. Als Pre-Build-Aufgabe verkabelt, wird Ihre Enumeration bei jedem Build neu erstellt, oder Sie können den T4 stattdessen nach Bedarf manuell ausführen.

CodingWithSpike
quelle
12

Angenommen, Sie haben Folgendes in Ihrer Datenbank:

table enums
-----------------
| id | name     |
-----------------
| 0  | MyEnum   |
| 1  | YourEnum |
-----------------

table enum_values
----------------------------------
| id | enums_id | value | key    |
----------------------------------
| 0  | 0        | 0     | Apple  |
| 1  | 0        | 1     | Banana |
| 2  | 0        | 2     | Pear   |
| 3  | 0        | 3     | Cherry |
| 4  | 1        | 0     | Red    |
| 5  | 1        | 1     | Green  |
| 6  | 1        | 2     | Yellow |
----------------------------------

Erstellen Sie eine Auswahl, um die benötigten Werte zu erhalten:

select * from enums e inner join enum_values ev on ev.enums_id=e.id where e.id=0

Wenn Sie den Quellcode für die Aufzählung erstellen, erhalten Sie Folgendes:

String enumSourceCode = "enum " + enumName + "{" + enumKey1 + "=" enumValue1 + "," + enumKey2 + ... + "}";

(Offensichtlich ist dies in einer Art Schleife aufgebaut.)

Dann kommt der lustige Teil: Kompilieren Sie Ihre Aufzählung und verwenden Sie sie:

CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters cs = new CompilerParameters();
cp.GenerateInMemory = True;

CompilerResult result = provider.CompileAssemblyFromSource(cp, enumSourceCode);

Type enumType = result.CompiledAssembly.GetType(enumName);

Jetzt haben Sie den Typ kompiliert und sind einsatzbereit.
Um einen in der DB gespeicherten Aufzählungswert abzurufen, können Sie Folgendes verwenden:

[Enum].Parse(enumType, value);

Dabei kann der Wert entweder der ganzzahlige Wert (0, 1 usw.) oder der Aufzählungstext / -schlüssel (Apple, Banana usw.) sein.

Sani Singh Huttunen
quelle
4
Inwiefern würde das tatsächlich helfen? Es gibt keine Typensicherheit und keine Intelligenz. Grundsätzlich ist es nur eine kompliziertere Art, eine Konstante zu verwenden, da er den Wert sowieso bereitstellen muss.
Runeborg
2
Sani - perfekt! Das war genau das, was ich brauchte. Für diejenigen, die den Grund für so etwas in Frage stellen, verwende ich eine Herstellerbibliothek, für die eine Eigenschaft auf den Namen einer Aufzählung gesetzt werden muss. Die Aufzählung schränkt den gültigen Wertebereich für eine andere Eigenschaft desselben Objekts ein. In meinem Fall lade ich Metadaten, einschließlich des gültigen Wertebereichs aus einer Datenbank. und nein, der Herstellercode unterstützt nicht die Übergabe einer Sammlung eines beliebigen Typs an die Eigenschaft. Danke
10

Ich zeige nur die Antwort von Pandincus mit dem Code "of the Shelf" und einer Erklärung: Sie benötigen zwei Lösungen für dieses Beispiel (ich weiß, dass dies auch über eine möglich ist;). Lassen Sie die fortgeschrittenen Schüler sie präsentieren ...

Hier ist also das DDL-SQL für die Tabelle:

USE [ocms_dev]
    GO

CREATE TABLE [dbo].[Role](
    [RoleId] [int] IDENTITY(1,1) NOT NULL,
    [RoleName] [varchar](50) NULL
) ON [PRIMARY]

Hier ist also das Konsolenprogramm, das die DLL produziert:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using System.Data.Common;
using System.Data;
using System.Data.SqlClient;

namespace DynamicEnums
{
    class EnumCreator
    {
        // after running for first time rename this method to Main1
        static void Main ()
        {
            string strAssemblyName = "MyEnums";
            bool flagFileExists = System.IO.File.Exists (
                   AppDomain.CurrentDomain.SetupInformation.ApplicationBase + 
                   strAssemblyName + ".dll"
            );

            // Get the current application domain for the current thread
            AppDomain currentDomain = AppDomain.CurrentDomain;

            // Create a dynamic assembly in the current application domain,
            // and allow it to be executed and saved to disk.
            AssemblyName name = new AssemblyName ( strAssemblyName );
            AssemblyBuilder assemblyBuilder = 
                    currentDomain.DefineDynamicAssembly ( name,
                            AssemblyBuilderAccess.RunAndSave );

            // Define a dynamic module in "MyEnums" assembly.
            // For a single-module assembly, the module has the same name as
            // the assembly.
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule (
                    name.Name, name.Name + ".dll" );

            // Define a public enumeration with the name "MyEnum" and
            // an underlying type of Integer.
            EnumBuilder myEnum = moduleBuilder.DefineEnum (
                    "EnumeratedTypes.MyEnum",
                    TypeAttributes.Public,
                    typeof ( int )
            );

            #region GetTheDataFromTheDatabase
            DataTable tableData = new DataTable ( "enumSourceDataTable" );

            string connectionString = "Integrated Security=SSPI;Persist " +
                    "Security Info=False;Initial Catalog=ocms_dev;Data " +
                    "Source=ysg";

            using (SqlConnection connection = 
                    new SqlConnection ( connectionString ))
            {

                SqlCommand command = connection.CreateCommand ();
                command.CommandText = string.Format ( "SELECT [RoleId], " + 
                        "[RoleName] FROM [ocms_dev].[dbo].[Role]" );

                Console.WriteLine ( "command.CommandText is " + 
                        command.CommandText );

                connection.Open ();
                tableData.Load ( command.ExecuteReader ( 
                        CommandBehavior.CloseConnection
                ) );
            } //eof using

            foreach (DataRow dr in tableData.Rows)
            {
                myEnum.DefineLiteral ( dr[1].ToString (),
                        Convert.ToInt32 ( dr[0].ToString () ) );
            }
            #endregion GetTheDataFromTheDatabase

            // Create the enum
            myEnum.CreateType ();

            // Finally, save the assembly
            assemblyBuilder.Save ( name.Name + ".dll" );
        } //eof Main 
    } //eof Program
} //eof namespace 

Hier ist die Konsolenprogrammierung, die die Ausgabe druckt (denken Sie daran, dass sie auf die DLL verweisen muss). Lassen Sie die fortgeschrittenen Schüler die Lösung vorstellen, um alles in einer Lösung mit dynamischem Laden zu kombinieren und zu überprüfen, ob bereits eine Build-DLL vorhanden ist.

// add the reference to the newly generated dll
use MyEnums ; 

class Program
{
    static void Main ()
    {
        Array values = Enum.GetValues ( typeof ( EnumeratedTypes.MyEnum ) );

        foreach (EnumeratedTypes.MyEnum val in values)
        {
            Console.WriteLine ( String.Format ( "{0}: {1}",
                    Enum.GetName ( typeof ( EnumeratedTypes.MyEnum ), val ),
                    val ) );
        }

        Console.WriteLine ( "Hit enter to exit " );
        Console.ReadLine ();
    } //eof Main 
} //eof Program
Yordan Georgiev
quelle
1
@YordanGeorgiev -Warum erklären Sie, flagFileExistswenn es nirgendwo anders in der Anwendung verwendet wird?
Michael Kniskern
2
Ich denke, es ist ein Fehler als; I)
Yordan Georgiev
5

Kommen wir nicht aus der falschen Richtung dazu?

Wenn sich die Daten während der Lebensdauer der bereitgestellten Version wahrscheinlich überhaupt ändern, ist eine Aufzählung einfach nicht geeignet, und Sie müssen ein Wörterbuch, einen Hash oder eine andere dynamische Sammlung verwenden.

Wenn Sie wissen, dass der Satz möglicher Werte für die Lebensdauer der bereitgestellten Version festgelegt ist, ist eine Aufzählung vorzuziehen.

Wenn Ihre Datenbank etwas enthalten muss , das den aufgezählten Satz repliziert, können Sie einen Bereitstellungsschritt hinzufügen, um die Datenbanktabelle mit dem endgültigen Satz von Aufzählungswerten zu löschen und neu zu füllen.

Brian Lowe
quelle
Ja und nein, ja, weil Sie richtig sind, ist der ganze Punkt statisch. Sie können Tippfehler vermeiden und wissen auch, was verfügbar ist. Mit Wörterbuch und Datenbank - könnte alles sein. Aber manchmal möchten Sie die Früchte beider Bäume, wenn Sie nur von einem pflücken dürfen.
Ken
4

Ich schreibe immer gerne meine eigene "benutzerdefinierte Aufzählung". Dann habe ich eine Klasse, die etwas komplexer ist, aber ich kann sie wiederverwenden:

public abstract class CustomEnum
{
    private readonly string _name;
    private readonly object _id;

    protected CustomEnum( string name, object id )
    {
        _name = name;
        _id = id;
    }

    public string Name
    {
        get { return _name; }
    }

    public object Id
    {
        get { return _id; }
    }

    public override string ToString()
    {
        return _name;
    }
}

public abstract class CustomEnum<TEnumType, TIdType> : CustomEnum
    where TEnumType : CustomEnum<TEnumType, TIdType>
{
    protected CustomEnum( string name, TIdType id )
        : base( name, id )
    { }

    public new TIdType Id
    {
        get { return (TIdType)base.Id; }
    }

    public static TEnumType FromName( string name )
    {
        try
        {
            return FromDelegate( entry => entry.Name.Equals( name ) );
        }
        catch (ArgumentException ae)
        {
            throw new ArgumentException( "Illegal name for custom enum '" + typeof( TEnumType ).Name + "'", ae );
        }
    }

    public static TEnumType FromId( TIdType id )
    {
        try
        {
            return FromDelegate( entry => entry.Id.Equals( id ) );
        }
        catch (ArgumentException ae)
        {
            throw new ArgumentException( "Illegal id for custom enum '" + typeof( TEnumType ).Name + "'", ae );
        }
    }

    public static IEnumerable<TEnumType> GetAll()
    {
        var elements = new Collection<TEnumType>();
        var infoArray = typeof( TEnumType ).GetFields( BindingFlags.Public | BindingFlags.Static );

        foreach (var info in infoArray)
        {
            var type = info.GetValue( null ) as TEnumType;
            elements.Add( type );
        }

        return elements;
    }

    protected static TEnumType FromDelegate( Predicate<TEnumType> predicate )
    {
        if(predicate == null)
            throw new ArgumentNullException( "predicate" );

        foreach (var entry in GetAll())
        {
            if (predicate( entry ))
                return entry;
        }

        throw new ArgumentException( "Element not found while using predicate" );
    }
}

Jetzt muss ich nur noch meine Aufzählung erstellen, die ich verwenden möchte:

 public sealed class SampleEnum : CustomEnum<SampleEnum, int>
    {
        public static readonly SampleEnum Element1 = new SampleEnum( "Element1", 1, "foo" );
        public static readonly SampleEnum Element2 = new SampleEnum( "Element2", 2, "bar" );

        private SampleEnum( string name, int id, string additionalText )
            : base( name, id )
        {
            AdditionalText = additionalText;
        }

        public string AdditionalText { get; private set; }
    }

Endlich kann ich es benutzen, wie ich will:

 static void Main( string[] args )
        {
            foreach (var element in SampleEnum.GetAll())
            {
                Console.WriteLine( "{0}: {1}", element, element.AdditionalText );
                Console.WriteLine( "Is 'Element2': {0}", element == SampleEnum.Element2 );
                Console.WriteLine();
            }

            Console.ReadKey();
        }

Und meine Ausgabe wäre:

Element1: foo
Is 'Element2': False

Element2: bar
Is 'Element2': True    
Traummaennlein
quelle
2

Sie möchten System.Web.Compilation.BuildProvider

Ich bezweifle auch die Weisheit, dies zu tun, aber dann gibt es vielleicht einen guten Anwendungsfall, an den ich nicht denken kann.

Was Sie suchen, sind Build-Anbieter, dh System.Web.Compilation.BuildProvider

Sie werden von SubSonic sehr effektiv verwendet . Sie können die Quelle herunterladen und sehen, wie sie verwendet werden. Sie benötigen nichts, was halb so kompliziert ist wie das, was sie tun.

Hoffe das hilft.

Binärer Worrier
quelle
0

Ich glaube nicht, dass es eine gute Möglichkeit gibt, das zu tun, was Sie wollen. Und wenn Sie darüber nachdenken, denke ich nicht, dass Sie das wirklich wollen.

Wenn Sie eine dynamische Aufzählung haben würden, bedeutet dies auch, dass Sie sie mit einem dynamischen Wert füttern müssen, wenn Sie darauf verweisen. Vielleicht könnten Sie mit viel Magie eine Art IntelliSense erreichen , das sich darum kümmert und eine Aufzählung für Sie in einer DLL-Datei generiert. Bedenken Sie jedoch, wie viel Arbeit erforderlich wäre, wie unwirksam es wäre, auf die Datenbank zuzugreifen, um IntelliSense-Informationen abzurufen, sowie den Albtraum der Versionskontrolle der generierten DLL-Datei.

Wenn Sie die Aufzählungswerte wirklich nicht manuell hinzufügen möchten (Sie müssen sie trotzdem zur Datenbank hinzufügen), verwenden Sie stattdessen ein Tool zur Codegenerierung, z. B. T4- Vorlagen. Klicken Sie mit der rechten Maustaste + Ausführen, und Sie haben Ihre Aufzählung statisch im Code definiert. Sie erhalten alle Vorteile der Verwendung von Aufzählungen.

Runeborg
quelle
0

Die Verwendung dynamischer Aufzählungen ist auf jeden Fall schlecht. Sie müssen sich die Mühe machen, die Daten zu "duplizieren", um einen klaren und einfachen Code zu gewährleisten, der in Zukunft leicht zu pflegen ist.

Wenn Sie mit der Einführung automatisch generierter Bibliotheken beginnen, werden zukünftige Entwickler mit Sicherheit mehr Verwirrung stiften, wenn sie Ihren Code aktualisieren müssen, als wenn Sie einfach Ihre Aufzählung im entsprechenden Klassenobjekt codieren.

Die anderen Beispiele klingen nett und aufregend, aber denken Sie an den Aufwand für die Code-Wartung im Vergleich zu dem, was Sie daraus erhalten. Werden sich diese Werte auch so häufig ändern?

Martin
quelle
0

Eine Möglichkeit, die Aufzählungen beizubehalten und gleichzeitig eine dynamische Werteliste zu erstellen, besteht darin, die Aufzählungen zu verwenden, die Sie derzeit mit einem dynamisch erstellten Wörterbuch haben.

Da die meisten Aufzählungen in dem Kontext verwendet werden, für den sie definiert sind, und die "dynamischen Aufzählungen" von dynamischen Prozessen unterstützt werden, können Sie die 2 unterscheiden.

Der erste Schritt besteht darin, eine Tabelle / Sammlung zu erstellen, die die IDs und Referenzen für die dynamischen Einträge enthält. In der Tabelle werden Sie automatisch größer als Ihr größter Enum-Wert.

Nun kommt der Teil für Ihre dynamischen Aufzählungen. Ich gehe davon aus, dass Sie die Aufzählungen verwenden, um eine Reihe von Bedingungen zu erstellen, die eine Reihe von Regeln anwenden. Einige werden dynamisch generiert.

Get integer from database
If Integer is in Enum -> create Enum -> then run Enum parts
If Integer is not a Enum -> create Dictionary from Table -> then run Dictionary parts.
Jackstine
quelle
0

Enum Builder Klasse

public class XEnum
{
    private EnumBuilder enumBuilder;
    private int index;
    private AssemblyBuilder _ab;
    private AssemblyName _name;
    public XEnum(string enumname)
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        _name = new AssemblyName("MyAssembly");
        _ab = currentDomain.DefineDynamicAssembly(
            _name, AssemblyBuilderAccess.RunAndSave);

        ModuleBuilder mb = _ab.DefineDynamicModule("MyModule");

        enumBuilder = mb.DefineEnum(enumname, TypeAttributes.Public, typeof(int));


    }
    /// <summary>
    /// adding one string to enum
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public FieldBuilder add(string s)
    {
        FieldBuilder f = enumBuilder.DefineLiteral(s, index);
        index++;
        return f;
    }
    /// <summary>
    /// adding array to enum
    /// </summary>
    /// <param name="s"></param>
    public void addRange(string[] s)
    {
        for (int i = 0; i < s.Length; i++)
        {
            enumBuilder.DefineLiteral(s[i], i);
        }
    }
    /// <summary>
    /// getting index 0
    /// </summary>
    /// <returns></returns>
    public object getEnum()
    {
        Type finished = enumBuilder.CreateType();
        _ab.Save(_name.Name + ".dll");
        Object o1 = Enum.Parse(finished, "0");
        return o1;
    }
    /// <summary>
    /// getting with index
    /// </summary>
    /// <param name="i"></param>
    /// <returns></returns>
    public object getEnum(int i)
    {
        Type finished = enumBuilder.CreateType();
        _ab.Save(_name.Name + ".dll");
        Object o1 = Enum.Parse(finished, i.ToString());
        return o1;
    }
}

ein Objekt erstellen

string[] types = { "String", "Boolean", "Int32", "Enum", "Point", "Thickness", "long", "float" };
XEnum xe = new XEnum("Enum");
        xe.addRange(types);
        return xe.getEnum();
Mahdi Khalili
quelle