Automatyczne tworzenie wyliczenia na podstawie wartości w tabeli wyszukiwania bazy danych?


116

Jak automatycznie utworzyć wyliczenie, a następnie użyć jego wartości w języku C # na podstawie wartości w tabeli wyszukiwania bazy danych (przy użyciu warstwy danych biblioteki przedsiębiorstwa)?

Na przykład, jeśli dodam nową wartość wyszukiwania w bazie danych, nie chcę ręcznie dodawać dodatkowej deklaracji statycznej wartości wyliczenia w kodzie - chciałbym, aby wyliczenie było zsynchronizowane z bazą danych.

Czy istnieje coś takiego?


Nie chcę tworzyć statycznego wyliczenia generowanego przez kod (zgodnie z artykułem w The Code Project Generator kodu wyliczenia - automatyczne generowanie kodu wyliczenia z tabel wyszukiwania w bazie danych ) i wolę, aby było to całkowicie automatyczne.


Czy byłoby możliwe, że próbujesz użyć wyliczenia w sposób, w którym istnieje lepsze rozwiązanie?
Dan

Jestem z @Dan, musi być lepszy sposób na zrobienie tego.
N_A

@mydogisbox, jaki jest lepszy sposób?
eran otzap

@eranotzer Właściwie, po zastanowieniu się nad tym przez chwilę, byłoby całkiem łatwo napisać krok przed kompilacją, który wysyła zapytanie do bazy danych i generuje z niej wyliczenie
N_A

1
Biorąc to pod uwagę, nie jestem pewien, co ma na myśli, mówiąc „Nie chcę tworzyć statycznego wyliczenia generowanego przez kod”, więc może to nie pasuje do potrzeb.
N_A,

Odpowiedzi:


97

Robię dokładnie to, ale aby to zadziałało , musisz wykonać jakiś rodzaj generowania kodu.

W moim rozwiązaniu dodałem projekt „EnumeratedTypes”. Jest to aplikacja konsolowa, która pobiera wszystkie wartości z bazy danych i konstruuje z nich wyliczenia. Następnie zapisuje wszystkie wyliczenia w zestawie.

Kod generowania wyliczenia wygląda następująco:

// 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");

Moje inne projekty w rozwiązaniu odwołują się do tego wygenerowanego zestawu. W rezultacie mogę następnie używać dynamicznych wyliczeń w kodzie, wraz z inteligencją.

Następnie dodałem zdarzenie po kompilacji, aby po zbudowaniu tego projektu „EnumeratedTypes” uruchamiał się sam i generował plik „MyEnums.dll”.

Nawiasem mówiąc, warto zmienić kolejność kompilacji projektu, tak aby „EnumeratedTypes” było budowane jako pierwsze. W przeciwnym razie, gdy zaczniesz używać dynamicznie generowanego pliku .dll, nie będziesz mógł wykonać kompilacji, jeśli plik .dll zostanie kiedykolwiek usunięty. (Problem w rodzaju kurczaka i jajka - inne projekty w rozwiązaniu wymagają tego pliku .dll do poprawnego skompilowania i nie możesz utworzyć pliku .dll, dopóki nie utworzysz rozwiązania ...)

Większość powyższego kodu uzyskałem z tego artykułu MSDN .

Mam nadzieję że to pomoże!


7
Dla tych, którzy nie wiedzą, jak uruchomić wynikowy plik wykonywalny po kompilacji: 1) Kliknij projekt prawym przyciskiem myszy 2) Kliknij właściwości 3) Kliknij opcję Zdarzenia kompilacji 4) W polu tekstowym „Wiersze poleceń zdarzenia po kompilacji” $ (TargetPath)
Miguel

Czy można wykonać dynamiczne wyliczenie z niestandardową definicją atrybutu, jak wspomniano w tym linku ?
Balagurunathan Marimuthu

49

Wyliczenia muszą być określone w czasie kompilacji, nie można dynamicznie dodawać wyliczeń w czasie wykonywania - i dlaczego miałbyś nie używać / odwoływać się do nich w kodzie?

Od Professional C # 2008:

Prawdziwa siła wyliczeń w C # polega na tym, że za kulisami są one tworzone jako struktury wywodzące się z klasy bazowej System.Enum. Oznacza to, że można wywołać metody przeciwko nim w celu wykonania pewnych przydatnych zadań. Należy zauważyć, że ze względu na sposób implementacji platformy .NET Framework nie ma utraty wydajności związanej z traktowaniem wyliczeń w sposób składniowy jako struktur. W praktyce po skompilowaniu kodu wyliczenia będą istniały jako typy pierwotne, podobnie jak int i float.

Nie jestem więc pewien, czy możesz używać wyliczeń tak, jak chcesz.


1
Nie jestem pewien, jakie jest rozumowanie billfredtom, ale moim było to, że mogłem uniknąć ręcznego wyszukiwania ciągów dla niektórych kluczy, zamiast tego wbudować je w mój kod. Po prostu wolę móc wykonywać logikę na silnie wpisanych wartościach zamiast słabych ciągów. Jedynym zastrzeżeniem byłoby to, że ponieważ mamy teraz kod, który opiera się na dynamicznie generowanym Enum, jeśli usuniemy wartość z bazy danych, następnym razem, gdy spróbujemy skompilować nasz kod, zakończy się to niepowodzeniem.
Pandincus

14
Plakat i 18 głosów poparcia trochę mijało się z celem. Wygląda na to, że chce wygenerowanych wyliczeń, a nie dynamicznych wyliczeń środowiska wykonawczego.
Matt Mitchell

+1. Wyliczenie to po prostu inny sposób definiowania stałych całkowitych (nawet jeśli System.Enumma jakąś dodatkową funkcjonalność). Zamiast pisać, const int Red=0, Green=1, Blue=3;piszesz enum { Red, Green, Blue }. Stała jest z definicji stała, a nie dynamiczna.
Olivier Jacot-Descombes

2
@Oliver Jeśli chcesz spierać się o semantykę, tak, masz rację. Ale zgadzam się z komentarzem Graphaina - uważam, że OP szuka wygenerowanych wyliczeń. Chce, aby wartości wyliczenia pochodziły z bazy danych i nie muszą ich na stałe kodować.
Pandincus

1
Albo ... powiedzmy, że pozwalam komuś w moim web.config definiować typy tokenów dla szablonów wiadomości e-mail dla mojego kodu szablonów wiadomości e-mail. Byłoby miło, gdyby moje istniejące wyliczenie o nazwie EmailTokens, które reprezentuje te typy ciągów, zostało wygenerowane na podstawie typów zdefiniowanych w moim pliku web.config. Więc jeśli ktoś doda nowy token e-mail w webconfig za pośrednictwem mojej wartości klucza, np. „Email, FName” i mam już wyliczenie, którego będę używał do reprezentowania tych tokenów, takich jak EmailTemplate. Email byłoby miło, gdyby ktoś mógł po prostu dodaj nowy token ciągu w tym kluczu w web.config, a moje wyliczenie automatycznie doda stałą
PositiveGuy

18

Czy to musi być rzeczywiste wyliczenie? Co powiesz na użycie Dictionary<string,int>zamiast tego?

na przykład

Dictionary<string, int> MyEnum = new Dictionary(){{"One", 1}, {"Two", 2}};
Console.WriteLine(MyEnum["One"]);

11
Nie próbowałbym tego robić w ten sposób. Tracisz kontrolę czasu kompilacji i stajesz się podatny na błędy pisania. Wszystkie zalety wyliczeń zniknęły. Możesz wprowadzić stałe łańcuchowe, ale wrócisz do punktu wyjścia.
Daniel Brückner

1
Zgadzam się. Ale pamiętaj, że źle wpisane struny zostaną przechwycone w czasie wykonywania. Po prostu dodaj przypadek testowy, aby objąć wszystkich członków wyliczenia.
Samouk

1
błędy w pisaniu nie stanowią problemu, jeśli używasz stałych zamiast literałów
Maslow

@Maslow Załóżmy, że masz na myśli wyliczenia, a nie stałe łańcuchowe.
Matt Mitchell

4
+1. Używanie słownika lub zestawu HashSet jest najbliższe temu, co mogłoby być dynamicznym wyliczeniem. W pełni dynamiczny oznacza, że ​​dzieje się to w czasie wykonywania i dlatego sprawdzanie błędów będzie musiało nastąpić w czasie wykonywania.
Olivier Jacot-Descombes

14

Zrobiłem to za pomocą szablonu T4 . Upuszczenie pliku .tt do projektu i skonfigurowanie programu Visual Studio do uruchamiania szablonu T4 jako kroku przed kompilacją jest dość trywialne.

T4 generuje plik .cs, co oznacza, że ​​możesz po prostu wysłać zapytanie do bazy danych i zbudować wyliczenie w pliku .cs na podstawie wyniku. Połączone jako zadanie przed kompilacją, utworzy ponownie wyliczenie przy każdej kompilacji lub możesz zamiast tego uruchomić T4 ręcznie w razie potrzeby.


12

Powiedzmy, że masz w swojej bazie danych:

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 |
----------------------------------

Skonstruuj selekcję, aby uzyskać potrzebne wartości:

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

Skonstruuj kod źródłowy wyliczenia, a otrzymasz coś takiego:

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

(oczywiście jest to zbudowane w jakiejś pętli).

Potem przychodzi zabawna część, kompilowanie wyliczenia i używanie go:

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

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

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

Teraz masz skompilowany typ i gotowy do użycia.
Aby uzyskać wartość wyliczenia przechowywaną w bazie danych, możesz użyć:

[Enum].Parse(enumType, value);

gdzie wartość może być liczbą całkowitą (0, 1 itd.) lub wyliczonym tekstem / kluczem (Apple, Banana itp.)


4
W jaki sposób to faktycznie pomogło? Nie ma bezpieczeństwa typów ani inteligencji. Zasadniczo jest to tylko bardziej skomplikowany sposób użycia stałej, ponieważ i tak musi on podać wartość.
Runeborg

2
Sani - doskonale! To było dokładnie to, czego potrzebowałem. Dla tych, którzy kwestionują przyczynę czegoś takiego, używam biblioteki dostawcy, która wymaga ustawienia właściwości na nazwę wyliczenia. Wyliczenie ogranicza prawidłowy zakres wartości dla innej właściwości tego samego obiektu. W moim przypadku ładuję metadane, w tym prawidłowy zakres wartości z bazy danych; i nie, kod dostawcy nie obsługuje przekazywania kolekcji żadnego typu do właściwości. Dzięki

10

Po prostu pokazuję odpowiedź Pandincusa z kodem "z półki" i kilka wyjaśnień: Potrzebujesz dwóch rozwiązań dla tego przykładu (wiem, że można to zrobić również za pomocą jednego;), pozwól zaawansowanym uczniom to przedstawić ...

Oto więc DDL SQL dla tabeli:

USE [ocms_dev]
    GO

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

Oto program konsoli, który tworzy bibliotekę dll:

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 

Oto programowanie konsoli wypisujące dane wyjściowe (pamiętaj, że musi odwoływać się do biblioteki dll). Niech zaawansowani studenci przedstawią rozwiązanie łączące wszystko w jednym rozwiązaniu z dynamicznym ładowaniem i sprawdzaniem, czy jest już skompilowana biblioteka dll.

// 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

1
@YordanGeorgiev - Dlaczego deklarujesz, flagFileExistsskoro nie jest używany nigdzie indziej w aplikacji?
Michael Kniskern

2
Myślę, że to błąd niż; I)
Yordan Georgiev

5

Czy nie idziemy do tego z niewłaściwego kierunku?

Jeśli dane prawdopodobnie w ogóle ulegną zmianie w okresie istnienia wdrożonej wersji, wyliczenie jest po prostu nieodpowiednie i musisz użyć słownika, skrótu lub innej kolekcji dynamicznej.

Jeśli wiesz, że zestaw możliwych wartości jest ustalony przez cały okres istnienia wdrożonej wersji, preferowane jest wyliczenie.

Jeśli w bazie danych musi znajdować się coś, co replikuje wyliczony zestaw, to dlaczego nie dodać kroku wdrażania, aby wyczyścić i ponownie wypełnić tabelę bazy danych ostatecznym zestawem wartości wyliczeniowych?


Tak i nie, tak, ponieważ masz rację, cały punkt jest statyczny. Możesz uniknąć błędów podczas pisania, a także wiedzieć, co jest dostępne. Ze słownikiem i bazą danych - może to być wszystko. Ale czasami chcesz owoce z obu drzew, kiedy możesz wybrać tylko z jednego.
Ken

4

Zawsze lubię pisać własne „niestandardowe wyliczenie”. Niż mam jedną klasę, która jest trochę bardziej złożona, ale mogę jej użyć ponownie:

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" );
    }
}

Teraz muszę tylko utworzyć wyliczenie, którego chcę użyć:

 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; }
    }

W końcu mogę go używać tak, jak chcę:

 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();
        }

A moje wyjście to:

Element1: foo
Is 'Element2': False

Element2: bar
Is 'Element2': True    

2

Chcesz System.Web.Compilation.BuildProvider

Wątpię też w sens robienia tego, ale może jest dobry przypadek użycia, o którym nie mogę myśleć.

To, czego szukasz, to Build Providers, czyli System.Web.Compilation.BuildProvider

bardzo efektywnie używane przez SubSonic , możesz pobrać źródła i zobaczyć, jak ich używają, nie będziesz potrzebować niczego w połowie tak skomplikowanego, jak to, co robią.

Mam nadzieję że to pomoże.



0

Myślę, że nie ma dobrego sposobu robienia tego, co chcesz. A jeśli o tym pomyślisz, nie sądzę, że tego naprawdę chcesz.

Jeśli chcesz mieć dynamiczne wyliczenie, oznacza to również, że musisz podać do niego wartość dynamiczną, gdy odwołujesz się do niego. Może z dużą ilością magii można uzyskać coś w rodzaju IntelliSense , który zajmie się tym i wygeneruje dla Ciebie wyliczenie w pliku DLL. Ale weź pod uwagę ilość pracy, która by to wymagała, jak nieskuteczny byłby dostęp do bazy danych w celu pobrania informacji IntelliSense, a także koszmar wersji kontrolującej wygenerowany plik DLL.

Jeśli naprawdę nie chcesz ręcznie dodawać wartości wyliczenia (i tak będziesz musiał dodać je do bazy danych) użyj zamiast tego narzędzia do generowania kodu, na przykład szablonów T4 . Kliknij prawym przyciskiem myszy i uruchom, a otrzymasz wyliczenie zdefiniowane statycznie w kodzie i uzyskasz wszystkie korzyści płynące z używania wyliczeń.


0

Używanie dynamicznych wyliczeń jest złe bez względu na sposób. Będziesz musiał uporać się z problemem „powielania” danych, aby zapewnić przejrzysty i łatwy kod, który będzie łatwy do utrzymania w przyszłości.

Jeśli zaczniesz wprowadzać automatycznie generowane biblioteki, z pewnością wprowadzisz więcej zamieszania wśród przyszłych programistów, którzy muszą zaktualizować swój kod, niż po prostu zakodować wyliczenie w odpowiednim obiekcie klasy.

Inne podane przykłady brzmią przyjemnie i ekscytująco, ale zastanów się nad narzutem związanym z utrzymaniem kodu w porównaniu z tym, co z niego otrzymasz. Czy te wartości będą się tak często zmieniać?


0

Jednym ze sposobów zachowania wyliczeń i jednoczesnego tworzenia dynamicznej listy wartości jest użycie aktualnie posiadanych wyliczeń z dynamicznie tworzonym słownikiem.

Ponieważ większość wyliczeń jest używana w kontekście, w jakim zostały zdefiniowane, a „dynamiczne wyliczenia” będą obsługiwane przez procesy dynamiczne, można wyróżnić 2.

Pierwszym krokiem jest utworzenie tabeli / kolekcji, w której znajdują się identyfikatory i referencje dla wpisów dynamicznych. W tabeli automatycznie zwiększasz wartość znacznie większą niż twoja największa wartość Enum.

Teraz pora na Twoje dynamiczne wyliczenia. Zakładam, że będziesz używać wyliczeń do tworzenia zestawu warunków, które stosują zestaw reguł, niektóre są generowane dynamicznie.

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.

0

Klasa konstruktora wyliczeń

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;
    }
}

stworzyć obiekt

string[] types = { "String", "Boolean", "Int32", "Enum", "Point", "Thickness", "long", "float" };
XEnum xe = new XEnum("Enum");
        xe.addRange(types);
        return xe.getEnum();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.