IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Enum généré dynamiquement


Sujet :

C#

  1. #1
    Membre du Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Novembre 2008
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Novembre 2008
    Messages : 54
    Points : 57
    Points
    57
    Par défaut Enum généré dynamiquement
    Bonjour,

    J'ai créé une Librairy qui contient des resources. J'aimerai, à la génération de la dll, créé dynamiquement un Enum contenant les keys présentes dans mes resources.

    J'ai trouver comment faire sur la MSDN : http://msdn.microsoft.com/en-us/libr...umbuilder.aspx

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    public static void Main()
        {
            // 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 aName = new AssemblyName("TempAssembly");
            AssemblyBuilder ab = currentDomain.DefineDynamicAssembly(
                aName, AssemblyBuilderAccess.RunAndSave);
     
            // Define a dynamic module in "TempAssembly" assembly. For a single-
            // module assembly, the module has the same name as the assembly.
            ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
     
            // Define a public enumeration with the name "Elevation" and an 
            // underlying type of Integer.
            EnumBuilder eb = mb.DefineEnum("Elevation", TypeAttributes.Public, typeof(int));
     
            // Define two members, "High" and "Low".
            eb.DefineLiteral("Low", 0);
            eb.DefineLiteral("High", 1);
     
            // Create the type and save the assembly.
            Type finished = eb.CreateType();
            ab.Save(aName.Name + ".dll");
     
            foreach( object o in Enum.GetValues(finished) )
            {
                Console.WriteLine("{0}.{1} = {2}", finished, o, ((int) o));
            }
        }
    L'inconvénient, c'est qu'il n'y a pas de : Main dans une Librairy.

    Merci d'avance.

  2. #2
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Qu'est-ce que tu veux faire exactement ?

    Parce que créer des enums à la volée me semble inutile en plus d'être complexe.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  3. #3
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    enumbuilder ne sert pas à ce que tu veux faire à priori
    si j'ai compris tu veux au moment de la compilation "ajouter" du code pour faire l'enum

    ca doit pouvoir se faire avec du code complexe qui peut etre utilisé par le compilateur pour faire quelque chose de particulier (event pre compilation je pense)

    le plus simple pour ca, c'est de se faire un générateur de code à la main, avec la reflection tu pourras trouver les ressources générées et faire le code de l'enum as string
    après il te faut un moyen d'appeler ce générateur de code et coller le code généré à chaque modification avant de recompiler la dll pour la déployer
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  4. #4
    Membre du Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Novembre 2008
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Novembre 2008
    Messages : 54
    Points : 57
    Points
    57
    Par défaut Détails de ma demande
    Pour être exacte, j'ai créé une dll dédiée à la traduction d'un de mes logiciels en cours de développement.
    Cette dll contient :
    • Public Static Class MoteurTraduction
    • Fichier Resources : contenant les clés pour la traduction
    • Fichier Resource par langue


    Dans ma Class Static, j'ai une fonction qui me retourne la chaine contenu dans le fichier resource de la CultureInfo en cours pour la clé donnée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Static String GetTraductionString(string key)
    Mon problème, c'est que j'ai créé mon code métier dans d'autre bibliothèque et que j'appelle méthode avec une clé saisie.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MessageBox.Show(MoteurTraduction.GetTraductionString("MessageBoxErrorNomClientTropLong"));
    Je voudrais à ne pas avoir à écrire "MessageBoxErrorNomClientTropLong" mais plutôt utiliser un Enum
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MessageBox.Show(MoteurTraduction.GetTraductionString(MessageBoxError.NomClientTropLong));
    Je voudrais éviter de devoir écrire l'enum pour plusieurs raisons :
    • Mon fichier resource contient aujourd'hui presque une centaines de clés, et je ne voudrais pas à avoir à tout écrire ou à utiliser un programme externe pour générer cet enum.
    • Si je supprime une valeur de l'enum, une erreur apparaitra à la compilation de la solution. M'indiquant ainsi, que la clé supprimé était utilisée.


    Est-ce que cela vous éclair ?

  5. #5
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Dans ce cas tu ne veux pas créer ton type dynamiquement à l'exécution, donc ton 1er code est inutile.

    L'outil Microsoft qui serait le plus pertinent est T4 qui permet d'écrire des templates de code.
    Après à voir s'il met à disposition une API permettant d'énumérer les ressources d'un autre projet...
    Si oui ça devrait être plutôt aisé : en gros une boucle + quelques "prints" pour l'entête de l'enum et ses éléments.

    Sinon il va falloir travailler toi même sur l'assembly de l'autre projet et utiliser CodeDom pour générer ton code C#.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  6. #6
    Membre du Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Novembre 2008
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Novembre 2008
    Messages : 54
    Points : 57
    Points
    57
    Par défaut
    Citation Envoyé par Pragmateek Voir le message
    Dans ce cas tu ne veux pas créer ton type dynamiquement à l'exécution, donc ton 1er code est inutile.

    L'outil Microsoft qui serait le plus pertinent est T4 qui permet d'écrire des templates de code.
    Après à voir s'il met à disposition une API permettant d'énumérer les ressources d'un autre projet...
    Si oui ça devrait être plutôt aisé : en gros une boucle + quelques "prints" pour l'entête de l'enum et ses éléments.

    Sinon il va falloir travailler toi même sur l'assembly de l'autre projet et utiliser CodeDom pour générer ton code C#.
    Effectivement, en cherchant, je venais également de découvrir j la Génération de code et modèles de texte T4 : http://msdn.microsoft.com/fr-fr/library/bb126445.aspx
    Cela me semble la meilleure solution. Merci pour vos conseils. Je répondre sur le sujet plus tard, pour vous dire si cela a fonctionné et comment j'ai fait.

    A+ et bon courage à tous.

  7. #7
    Membre du Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Novembre 2008
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Novembre 2008
    Messages : 54
    Points : 57
    Points
    57
    Par défaut Première Solution
    Bonjour à tous, voici le code que j'ai mis en place et qui fonctionne.

    Dans le projet de ma bibliothèque, j'ai créé un fichier ce nommant : "AssemblyInfo.tt" dans le répertoire : Properties
    Je l'ai inclus dans mon projet. Ensuite, j'ai ouvert le fichier : "AssemblyInfo.tt" dans Visual Studio 2012.

    A l'intérieur de celui-ci j'ai écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    <#@ template debug="false" hostspecific="true" language="C#" #>
    <#@ output extension=".cs" #>
    <#@ assembly name="System.Windows.Forms" #>
    <#@ import namespace="System.Resources" #>
    <#@ import namespace="System.Collections" #>
    <#@ import namespace="System.IO" #>
    <#@ import namespace="System.ComponentModel.Design" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ import namespace="System.Reflection" #>
    <#
     
        var nameSpace = "Superviseur.LangageRessources";
        var enumSubName ="Resx";
        var enumValidator = "Validator";
        var enumMessageBox ="MessageBox";
        var enumButton ="Button";
        var enumOther = "Other";
     
        var fileName = "Resources.resx";
        var filePath = Path.Combine(Path.GetDirectoryName(this.Host.ResolvePath("")), "Properties", fileName);
     
        var filettcs = "AssemblyInfo1.cs";
        var filePathttcs = Path.Combine(Path.GetDirectoryName(this.Host.ResolvePath("")), "Properties", filettcs);
        System.IO.StreamWriter writer = new StreamWriter(filePathttcs, false);
        writer.Write("");
        writer.Close();
     
     
        using (var reader = new ResXResourceReader(filePath))
        {
            reader.UseResXDataNodes = true;
     
    		List<DictionaryEntry> listeValidator = new List<DictionaryEntry>();
    		List<DictionaryEntry> listeMessageBox = new List<DictionaryEntry>();
    		List<DictionaryEntry> listeButton = new List<DictionaryEntry>();
    		List<DictionaryEntry> listeOther = new List<DictionaryEntry>();		
     
    		foreach(DictionaryEntry entry in reader) 
    		{
    			string keyName = entry.Key.ToString();
     
    			if (keyName.StartsWith(enumValidator))
    			{
    				listeValidator.Add(entry);
    			}else
    			{
    				if (keyName.StartsWith(enumMessageBox))
    				{
    					listeMessageBox.Add(entry);
    				}else
    				{
    					if (keyName.StartsWith(enumButton))
    					{
    						listeButton.Add(entry);
    					}else
    					{
    						listeOther.Add(entry);
    					}
    				}
    			}			
    		} 
    #>
    namespace <#=nameSpace#>
    {
        public enum <#=enumSubName + enumValidator#>
        {
            <#  foreach(DictionaryEntry entry in listeValidator) { 
                var name = entry.Key;
                var node = (ResXDataNode)entry.Value;
                var value = node.GetValue((ITypeResolutionService) null);
                var comment = node.Comment;
                var summary = value;
                if (!String.IsNullOrEmpty(comment)) summary += " - " + comment;
            #>
     
            /// <summary>
            /// <#= summary #>
            /// </summary>
            <#= name #>,
            <# } #>
     
        }
     
    	public enum <#=enumSubName + enumMessageBox#>
        {
            <#  foreach(DictionaryEntry entry in listeMessageBox) { 
                var name = entry.Key;
                var node = (ResXDataNode)entry.Value;
                var value = node.GetValue((ITypeResolutionService) null);
                var comment = node.Comment;
                var summary = value;
                if (!String.IsNullOrEmpty(comment)) summary += " - " + comment;
            #>
     
            /// <summary>
            /// <#= summary #>
            /// </summary>
            <#= name #>,
            <# } #>
     
        }
     
    	public enum <#=enumSubName + enumButton#>
        {
            <#  foreach(DictionaryEntry entry in listeButton) { 
                var name = entry.Key;
                var node = (ResXDataNode)entry.Value;
                var value = node.GetValue((ITypeResolutionService) null);
                var comment = node.Comment;
                var summary = value;
                if (!String.IsNullOrEmpty(comment)) summary += " - " + comment;
            #>
     
            /// <summary>
            /// <#= summary #>
            /// </summary>
            <#= name #>,
            <# } #>
     
        }
     
    	public enum <#=enumSubName + enumOther#>
        {
            <#  foreach(DictionaryEntry entry in listeOther) { 
                var name = entry.Key;
                var node = (ResXDataNode)entry.Value;
                var value = node.GetValue((ITypeResolutionService) null);
                var comment = node.Comment;
                var summary = value;
                if (!String.IsNullOrEmpty(comment)) summary += " - " + comment;
            #>
     
            /// <summary>
            /// <#= summary #>
            /// </summary>
            <#= name #>,
            <# } #>
     
        }
     
    }
     
     
    <#
        }
    #>
    Ce code me permet de séparer les clés présentent dans mon fichier ressource, par rapport au début des chaînes de caractère de celles-ci.
    Une fois les clés triées dans mes listes, je génère le code C# me permettant de créer mes Enums dynamiquement.

    Si vous avez des avis sur mon code pour le rendre plus propre, je suis preneur.

    Merci encore pour votre aide.

  8. #8
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Le seul truc que je verrais bien autrement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    if (keyName.StartsWith(enumValidator))
    {
        listeValidator.Add(entry);
    }
    else if (keyName.StartsWith(enumMessageBox))
    {
        listeMessageBox.Add(entry);
    }
    else if (keyName.StartsWith(enumButton))
    {
        listeButton.Add(entry);
    }
    else
    {
        listeOther.Add(entry);
    }
    Sinon très joli travail, c'est sûr ça servira à d'autres.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  9. #9
    Membre du Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Novembre 2008
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Chef de projet MOA
    Secteur : Boutique - Magasin

    Informations forums :
    Inscription : Novembre 2008
    Messages : 54
    Points : 57
    Points
    57
    Par défaut Problème avec T4
    Salut,

    j'ai remarqué un petit inconvénient à l'utilisation de T4, il exécute le code du fichier "*.tt" uniquement lorsque celui-ci a été modifié.
    J'ai cherché toute la journée d'hier pour trouver comment forcer son exécution, sans réussir.

    J'ai trouvé ce site qui me paraissait bien sans réussir à le faire fonctionner
    http://blogs.clariusconsulting.net/k...al-studio-sdk/

    Est-ce quelqu'un connait une solution ?

    Merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Récuperer la valeur d'input généré dynamiquement
    Par pivalone dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 26/06/2007, 14h45
  2. checkbox généré dynamiquement
    Par inf018 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 10/03/2007, 18h25
  3. [MySQL] Appel d'une fonction au nom généré dynamiquement
    Par FrankOVD dans le forum PHP & Base de données
    Réponses: 14
    Dernier message: 10/06/2006, 14h36
  4. [VB.NET]Comment identifier contrôles générés dynamiquement?
    Par toniolol dans le forum Windows Forms
    Réponses: 8
    Dernier message: 21/12/2005, 07h58
  5. écrire dans un champs généré dynamiquement
    Par scoder dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 08/12/2004, 10h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo