c# class string - Enum dynamique en C #




7 Answers

Je fais exactement cela, mais vous devez faire une sorte de génération de code pour que cela fonctionne.

Dans ma solution, j'ai ajouté un projet "EnumeratedTypes". C'est une application console qui récupère toutes les valeurs de la base de données et en construit les énumérations. Ensuite, il enregistre toutes les énumérations dans un assemblage.

Le code de génération enum est comme ceci:

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

Mes autres projets dans la solution font référence à cet assemblage généré. Par conséquent, je peux ensuite utiliser les énumérations dynamiques dans le code, avec intellisense.

Ensuite, j'ai ajouté un événement de post-construction afin que, après la construction du projet "EnumeratedTypes", il s'exécute et génère le fichier "MyEnums.dll".

En passant, il est utile de changer l' ordre de construction de votre projet afin que "EnumeratedTypes" soit construit en premier. Sinon, une fois que vous commencerez à utiliser votre fichier .dll généré dynamiquement, vous ne pourrez pas générer de version si le fichier .dll est supprimé. (Chicken and Egg genre de problème - vos autres projets dans la solution ont besoin de ce fichier .dll pour construire correctement, et vous ne pouvez pas créer le fichier .dll jusqu'à ce que vous construisez votre solution ...)

J'ai obtenu la plupart du code ci-dessus de cet article msdn .

J'espère que cela t'aides!

c++ if

Comment puis-je créer une énumération dynamique (et ensuite utiliser les choix d'énumération) en C # en fonction des valeurs d'une table de recherche de base de données (en utilisant la couche de données de la bibliothèque d'entreprise)?

Par exemple, si j'ajoute une nouvelle valeur de recherche dans la base de données, je ne souhaite pas ajouter la déclaration de valeur enum statique supplémentaire dans le code.

Y a-t-il une chose pareille? Je ne veux pas créer une énumération statique générée par code (comme dans l'article The Code Project Générateur de code Enum - Génération de code enum automatiquement à partir des tables de consultation de base de données ) et préférerait que ce soit complètement dynamique.




Est-ce que ça doit être une énumération? Pourquoi ne pas utiliser un Dictionary<string,int> place?

par exemple

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



Disons que vous avez les éléments suivants dans votre base de données:

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

Construisez un select pour obtenir les valeurs dont vous avez besoin:

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

Construis le code source de l'énumération et tu obtiendras quelque chose comme:

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

(évidemment, cela est construit dans une boucle de quelque sorte.)

Puis vient la partie amusante, Compiler votre énumération et l'utiliser:

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

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

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

Vous avez maintenant le type compilé et prêt à l'emploi.
Pour obtenir une valeur enum stockée dans la base de données, vous pouvez utiliser:

[Enum].Parse(enumType, value);

où valeur peut être soit la valeur entière (0, 1, etc.) ou le texte / clé enum (Apple, Banana, etc.)




Vous voulez System.Web.Compilation.BuildProvider

Je doute aussi de la sagesse de faire cela, mais alors il y a peut-être un bon cas d'utilisation auquel je ne peux penser.

Ce que vous cherchez sont Build Providers ie System.Web.Compilation.BuildProvider

Ils sont utilisés très efficacement par SubSonic , vous pouvez télécharger la source et voir comment ils les utilisent, vous n'aurez besoin de rien de moins compliqué que ce qu'ils font.

J'espère que cela t'aides.







Utiliser des énumérations dynamiques est mauvais, peu importe de quelle façon. Vous devrez passer par la «duplication» des données pour garantir un code clair et facile à maintenir à l'avenir.

Si vous commencez à introduire des librairies générées automatiquement, vous êtes à coup sûr source de plus de confusion pour les futurs développeurs qui doivent mettre à jour votre code plutôt que de simplement enumérer votre code dans l'objet de classe approprié.

Les autres exemples donnés sont intéressants et excitants, mais pensez aux frais généraux liés à la maintenance du code par rapport à ce que vous obtenez. Aussi, ces valeurs vont-elles changer si souvent?




Ne venons-nous pas dans cette direction?

Si les données sont susceptibles de changer pendant la durée de vie de la version déployée, une énumération n'est tout simplement pas appropriée et vous devez utiliser un dictionnaire, un hachage ou une autre collection dynamique.

Si vous savez que l'ensemble des valeurs possibles est fixé pour la durée de vie de la version déployée, une énumération est préférable.

Si vous devez avoir quelque chose dans votre base de données qui réplique l'ensemble énuméré, alors pourquoi ne pas ajouter une étape de déploiement pour effacer et repeupler la table de base de données avec l'ensemble définitif de valeurs enum?




Related