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 :

Func, Expression et CSharpCodeProvider


Sujet :

C#

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut Func, Expression et CSharpCodeProvider
    Bonjour à tous,

    Je suis en train de réaliser un moteur de règle pour les besoins d'un projet et je rencontre 2 soucis.

    1)Le premier est la création de règle, celles-ci sont stockées dans une base de données SQL puis récupérer dans un service windows (au démarrage et lors de la modification d'une des règles via le back office).
    Les règles sont de la forme :
    Name Operator Target
    Nom NotEqual toto
    Code.Length Equal 5
    DateNaissance GreaterThan 01/01/1900

    Name, Code et DateNaissance correspondent aux attributs de ma classe.

    Afin de créer mes règles côtés C# voilà les 2 procédures que j'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    public static Func<T, bool> CompileRule<T>(Rule r)
    {
        var paramUser = Expression.Parameter(typeof(T));            
        Expression expr = BuildExpr<T>(r, paramUser);            
        return Expression.Lambda<Func<T, bool>>(expr, paramUser).Compile();
    }
    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
     
    static Expression BuildExpr<T>(Rule r, ParameterExpression param)
    {
     
        var left = MemberExpression.Property(param, r.MemberName);           
        var tProp = typeof(T).GetProperty(r.MemberName).PropertyType;
        ExpressionType tBinary;            
        if (ExpressionType.TryParse(r.Operator, out tBinary))
        {
            var right = Expression.Constant(Convert.ChangeType(r.TargetValue, tProp)); 
            return Expression.MakeBinary(tBinary, left, right);
        }
        else
        {
            var method = tProp.GetMethod(r.Operator);
            var tParam = method.GetParameters()[0].ParameterType;
            var right = Expression.Constant(Convert.ChangeType(r.TargetValue, tParam));
            return Expression.Call(left, method, right);
        }
    }
    Lorsque je viens pour créer mes règles 1 et 3, pas de soucis cela fonctionne mais pour la règle 2 il y a une erreur qui dit que Code.Length n'est pas un membre de ma classe. Cela est normal car Length est une propriété de la classe string pour retourner la longueur de la chaîne. J'ai regardé sur le net pour pouvoir retourner les propriétés imbriqués pour une classe mais je ne trouve pas de solution. L'erreur se produit dans la 2ème procédure sur la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var left = MemberExpression.Property(param, r.MemberName);
    Pour le moment j'ai contourné le problème en ajoutant un attribut Code_Length dans ma classe, mais cela n'est pas propre si je dois créer un attribut pour chaque propriété. De plus, mes classes sont créer dynamiquement via la classe CSharpCodeProvider afin de pouvoir les recompiler en cas de modification depuis le back office.

    2) Le second problème vient justement de la gestion dynamique de mes classes pour créer mes règles. La fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Func<T, bool> CompileRule<T>(Rule r)
    attendant un type T qui correspond à une classe or je ne peux pas le préciser physiquement puisque je gère plusieurs classes en mémoire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Func<Personne, bool> compiledRule = CompileRule<Personne>(rule);
    Mes classes sont créer comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    CSharpCodeProvider cl = new CSharpCodeProvider();
    var cp = new CompilerParameters();
    cp.GenerateInMemory = true;
     
    var res = cl.CompileAssemblyFromSource(
                    cp,
                    "using System; public class Personne \t{ public string Nom {get; set;} public string Code {get; set;} public DateTime DateNaissance {get; set;} public string Hello() { return \"Bonjour \" + Nom + \" !\"; } }"
                );
     
    var type = res.CompiledAssembly.GetType("Personne");
    var obj = Activator.CreateInstance(type);
    La seule solution que je vois, serait de gérer dynamiquement dans une classe statique, autant de "Func" que j'ai de classe mais cela va vite devenir compliquer si tout est dynamique.
    La solution n'est pas définitive si quelqu'un m'en propose une meilleure.

  2. #2
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    Bonjour,

    La solution que j'avais utilisé (de mémoire) est de passer par une classe proxy qui contient une propriété T (ou object je me souviens plus) qui est la classe que tu désire, tes règles dérive de cette classe et override cette propriété (qui est le vrai type attendu, personne dans ton cas) et tu récupère cette instance.

    J'ai un exemple de code à la maison, je peux regarder ce soir si tu ne comprend pas ce que j'essaye de t'expliquer.
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut
    Je veux bien un exemple si tu as, même si je pense avoir compris le principe.

  4. #4
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    Ok en rentrant ce soir je t envois un truc.
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut
    Ca marche merci

  6. #6
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    Bonsoir,

    Alors en regardant mieux ce que tu as fait, je constate qu'il faut que tu renseigne le type que tu utilise, il te soit manque une colonne "type", soit déterminer le type par rapport à un pattern, par exemple quand ça commence par date tu sait que c'est une date, ou si le nom commence par toto tu sait que c'est une classe Toto, ou tu essaye de caster les valeur jusqu’à ce que ça "match" et correspond au type attendu. Il y a pleins de solutions possible mais à un moment il faut que détermine ce que tu va utiliser.
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  7. #7
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut
    En fait j'ai réussi à trouver une solution en utilisant la réflexion, ce qui m'a demandé pas mal de recherche car je suis un peu rouillé côté C# ^^

    Mes classes seront instancié via
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Activator.CreateInstance(type)
    Partant de là, je me suis demandé s'il était possible (sachant que tout est possible ^^) de faire l'inverse, c'est à dire de rendre une classe instancié "hard code" en instance générique. Je me suis donc rapproché de la classe MethodInfo qui permet de faire cela.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    MethodInfo method = typeof(RuleManager).GetMethod("CompileRule")
    MethodInfo generic = method.MakeGenericMethod(type)
    var t = generic.Invoke(rm, new object[] { rules[0] });
    RuleManager est ma classe avec mes 2 procédures pour construire mon expression (ma règle) et créer ma fonction généric. t correspond donc à ma fonction typée et compilée.
    Ensuite pour utiliser cette règle, je réutilise la classe MethodInfo pour appeler un procédure de ma classe RuleManager, qui prend en paramètre une fonction typée et compilée et un objet du dit type. Cette procédure va évaluer la règle et me retourner le résultat.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    MethodInfo method2 = typeof(RuleManager).GetMethod("Valider")
    MethodInfo generic2 = method2.MakeGenericMethod(type)
    var bresult = generic.Invoke(rm, new object[] { t, obj });
     
    public class RuleManager{
    ...
     
    public bool Valider<T>(Func<T, bool> exp, T objet){
    return exp(objet);
    }
    ...
    }
    Je n'ai pas encore tout tester mais pour le moment cela répond bien à ma problématique d'utiliser une classe généric dans du "hard code". Je ne sais pas si c'est la meilleur façon de faire, mais c’en est une qui fonctionne.

  8. #8
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    T'es ps juste en train de réinventer le principe du dynamic ?
    http://msdn.microsoft.com/fr-fr/library/dd264736.aspx
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut
    J'ai regardé le type dynamic mais cela ne règle pas mon problème. Comment utiliser le type dynamic avec ma fonction de compilation de règle ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    private Func<T, bool> CompileRule<T>(Rule r)
    {...}
    T doit forcément être un type d'une classe en "hard code" or mes classes sont instanciées via :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Type type = res.CompiledAssembly.GetType("xxxxxx");     
    var obj = Activator.CreateInstance(type);
    Et il n'est pas possible de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Func<type, bool> compiledRule = CompileRule<type>(rule);
    Suis-je passé à côté de quelque chose ?

  10. #10
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    Citation Envoyé par Ornitho76 Voir le message
    J'ai regardé le type dynamic mais cela ne règle pas mon problème. Comment utiliser le type dynamic avec ma fonction de compilation de règle ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    private Func<T, bool> CompileRule<T>(Rule r)
    {...}
    T doit forcément être un type d'une classe en "hard code" or mes classes sont instanciées via :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Type type = res.CompiledAssembly.GetType("xxxxxx");     
    var obj = Activator.CreateInstance(type);
    Et il n'est pas possible de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Func<type, bool> compiledRule = CompileRule<type>(rule);
    Suis-je passé à côté de quelque chose ?
    Miais pourquoi tu ne fait pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Activator.CreateInstance(typeof(T))
    il me semble que ce n'est que de cela que tu as besoin.
    Parce que sinon il me manque un morceau pour comprendre ton besoin exact .
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  11. #11
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut
    Les classes que je vais instancier via l'Activator auront toutes des propriétés différentes (ex. Personne, Chien, Coordonnée, ...). De plus, ces classes seront générées à partir d'un paramétrage qui sera stockée côté SQL et qui pourra évoluer.

    Les règles seront elles aussi stockées côté SQL et seront liées aux classes, si bien que ma classe Personne aura ses propres règles (ex. Personne.Nom != null, Personne.DateNaissance < DateTime.Now ...), ma classe Chien aura elle aussi ses propres règles (ex. Chien.Age < 20 ...).

    Si j'utilise l'Activator avec le typeof(T), ça sous-entend que les classes que je vais compiler dynamiquement ont toutes les mêmes propriétés or ce n'est pas le cas, ou alors il y a quelque chose que je n'ai pas compris sur l'utilisation de cette classe.

    Si je résume le projet :
    - Compilation de toutes mes classes en mémoire via la classe CompilerParameters.
    - Création de mes règles pour chaque classe en précisant le type de la classe.

    Lorsque le service va recevoir une demande de contrôle, il va instancier un objet de la classe qu'il faut contrôler puis récupérer l'ensemble des règles déjà compilé pour cette classe et enfin effectuer les tests de l'objet.

  12. #12
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    J'ai mis un petit proc en PJ, est ce que cela se rapproche de ce que tu veux faire Pièce jointe 158322?
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  13. #13
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut
    Ca y ressemble pour les règles mais pas pour la génération des classes, il faut que la classe Personne soit créer dynamiquement et donc du coup le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IPropertieRuleExtension<Personne> nameValidator = (IPropertieRuleExtension<Personne>)Activator.CreateInstance(cl.LoadAssemblyReturnTypeClass());
    Ne fonctionnera pas car il faut remplacer Personne par une variable de type Personne et cela n'est pas possible.

    Il faut savoir que depuis une interface BackOffice, il sera possible de créer du paramétrage et donc de nouvelle classe avec des propriétés propre à cette classe.

  14. #14
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    Oki, je vois ce qui te manque.

    Quand j ai 5 min je regarde pour te faire un truc.
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  15. #15
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    Pour que tu puisse avancer tout seul il faut que tu fasse de l'injection de dependance.


    Je te conseille Unity pour le coup https://unity.codeplex.com/

    Unity de permettre d'enregistrer une interface par exemple et de lui associé un type d'instance et de cle,

    L'idée est la suivante, quand tu créé tes classes Personne, tu cré les regles associé, tu enregistre ta classe personne avec un mot clé, tu enregistre tes validateur avec eux aussi un pattern de mot clé.Unity te permettra de résoudre des instance de cette manière par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    IUnityContainer container;
            container.Resolve(Type t, string name, ResolverOverride[] resolverOverrides);
    Je te propose de regarder.
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  16. #16
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut
    Ok, je vais me documenter sur ça, merci

  17. #17
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    J'ai remanié un peux le code pour te montrer un petit proc, tu peux pousser le concept beaucoup plus loin, surtout que Unity te permet de faire des chose assez magique quand tu sait l'utiliser. Tu pourrais aussi générer des attributs de décoration (façon AOP) a chaque fois que tu génère tes classes et ainsi automatiser la validation, et t’éviter de générer des classes inutiles.

    Je pense que ça fait a peu près ce que tu voulais.

    Cordialement.

    DynamiqueValidation.zip


    edit : Pense à activer la restauration des packages nugets
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  18. #18
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut
    J'ai regardé le code que tu as envoyé, effectivement ça à l'air pas mal, il faut juste que je me documente un peu plus sur Unity afin de pouvoir le manipuler correctement.
    Encore merci.

  19. #19
    Membre éprouvé Avatar de worm83
    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Février 2010
    Messages
    459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2010
    Messages : 459
    Points : 1 118
    Points
    1 118
    Par défaut
    Juste deux petites précisions pour que mon intervention soit complète :

    Si tu es pressé, tu peux te passer de Unity, le IUnityContainer n'est au final qu'un dictionnaire qui pour un type/interface enregistré est capable de te créer une instance associé. Tu pourrais te créer ton propre resolver.
    Il existe aussi d'autre frameworks d'IOC qui ont chacun leurs qualités et défauts, tu peux aussi regarder MEF (qui n'est pas un Framework d'IOC à proprement parler) qui fait de l'introspection dynamique afin de rechercher les dépendances attendu (utile pour des plugins) ce qui pourrais aussi répondre à ton problème (je ne sais pas où, et comment tu génère tes classes), je n'en ai pas parlé car ce n'était pas ta première question.

    Les avantages de Unity :

    Tu peux enregistrer pour une Interface un type complet à instancier. Tu peux par exemple dire à Unity que pour un IPropertieRuleExtension<T> si le T attendu est un "IBidule" et que tu as plusieurs dérivé de IBidule définir celui que tu veux. Unity est capable de résoudre des dépendances de manière très puissante, et abstraites. Pour un IPropertieRuleExtension<Personne> enregistré avec une clé PersonneContainer, tu peux demander à Unity la chose suivante

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
                IPropertieRuleExtension<Personne> val = container.Resolve<IPropertieRuleExtension<Personne>>("PersonneContainer");
    ou tu peux écrire ce genre de chose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
              IPropertieRuleExtension val = container.Resolve(typeof(IPropertieRuleExtension<>)) as IPropertieRuleExtension;

    Ensuite Unity gère la duré de vie de ton objet, pour une même implémentation tu peux demander à Unity de t'en faire un Singleton, une instance à chaque demande, un multiton ect... si tu as besoin d'une durée de vie exotique, tu peux implémenter ta propre logique.

    Unity possède beaucoup de plugins et extension ce qui permet de booster la productivité une fois cette brique maitriser, et est une brique Microsoft.

    Bon courage.
    "Le train de tes injures roule sur le rail de mon indifférence."

    "Monde de merde !!"

    Georges Abitbol.

  20. #20
    Membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    110
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 110
    Points : 55
    Points
    55
    Par défaut
    Comme dirait Gandalf : "Je reviens vers vous en ces temps difficiles..."

    Je n'avais pas vu ta dernière réponse car je suis sur un autre projet en parallèle (qui n'a rien à voir puisque c'est du BI) mais pour faire simple je ne suis pas pressé puisque le projet est en cours de développement

    J'ai analysé le code que tu m'as envoyé et j'ai une question sur le code suivant :
    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
     
    public class Personne
        {
            public Personne()
            {
                Name = "tata";
            }
            public string Name { get; set; }
        }
     
    public partial class GeneratedNameAttribute : IPropertieRuleExtension<Personne>
        {
            public bool Validate(Personne value)
            {
                return value.Name.Length != 5;
            }
     
            public bool Validate(object type)
            {
                return this.Validate((Personne)type);
            }
        }
     
        public class PersonneValidator : Validator<Personne, GeneratedNameAttribute> { }
    Ce code est généré dynamiquement et ça marche très bien. Seulement si je veux ajouter un second attribut à ma classe Personne (Prenom par exemple), je rencontre un problème puisqu'il n'est pas possible de créer une seconde classe PersonneValidator de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public partial class GeneratedPrenomAttribute : IPropertieRuleExtension<Personne>
        {
            public bool Validate(Personne value)
            {
                return value.Prenom.Length != 5;
            }
     
            public bool Validate(object type)
            {
                return this.Validate((Personne)type);
            }
        }
    public class PersonneValidator : Validator<Personne, GeneratedPrenomAttribute> { }
    La solution bête serait de nommer la classe en fonction de la propriété que je veux contrôler mais c'est pas propre du tout, je vais me retrouver avec autant de classe Validator que d'attribut dans mes classes.

    N'y-a-t-il pas une meilleure solution ? Par exemple avec une classe "RuleManager" qui gère l'ensemble des règles pour toutes les classes et qui serait appelé lors de la validation des attributs d'une classe ? Et du coup, créer le petit frère (ou la petite soeur) qui serait "ClassManager" et qui contiendrait l'ensemble des classes utilisateurs créés dynamiquement .

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 5
    Dernier message: 14/04/2011, 13h57
  2. [expression régulière] mon cerveau fait des noeuds..
    Par nawac dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 27/05/2003, 10h06
  3. [langage] expression reguliere motif répétitif dans 1 pattern
    Par comme de bien entendu dans le forum Langage
    Réponses: 11
    Dernier message: 09/04/2003, 16h14
  4. Expressions réguliéres
    Par Tooms dans le forum Langage
    Réponses: 4
    Dernier message: 06/12/2002, 18h42
  5. Réponses: 5
    Dernier message: 11/06/2002, 15h21

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