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 :

[Generics] Diriger vers la bonne méthode


Sujet :

C#

  1. #1
    Membre éprouvé Avatar de anthyme
    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 559
    Points : 1 257
    Points
    1 257
    Par défaut [Generics] Diriger vers la bonne méthode
    Bonjour,

    J'ai tenté quelque chose de peut etre trop ambitieux :

    appeller une methode avec un variable a type static avec en argument une variable généric...

    en gros ca donne ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
            protected override void RegisterAllViewEvents<T>(T view)
            {
                RegisterViewEvents(view);
            }
     
            public void RegisterViewEvents(ISearchFormView view)
            {
                view.SearchExecuted += new EventHandler(SearchExecuted);
            }
     
            public void RegisterFiltersEvents(ISearchFilterView view)
            {
                view.FilterApllied += new EventHandler(FilterApllied);
            }
    Evidement cela ne marche pas (ce genre de lien doivent etre fait à la compilation) comment fait un truc propre sans avoir a faire dans RegisterAllViewEvents des Test sur le type en entrée ?

    merci

  2. #2
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    J'ai pas tout compris ce que tu voulais faire. Mais tu peux rajouter une contrainte sur T avec une clause where.
    Introduction à Silverlight 4 (new) ; Localisation d'une application Silverlight (new) ;
    Mon espace perso[/B]

    La connaissance s’acquiert par l’expérience, tout le reste n’est que de l’information. Albert Einstein[/SIZE]

  3. #3
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par anthyme Voir le message
    Bonjour,
    J'ai tenté quelque chose de peut etre trop ambitieux :
    Ce que tu veux, c'est appeler l'une ou l'autre surcharge d'une méthode non générique dans une fonction générique en fonction du type T ? Je ne crois pas que ce soit possible simplement, à moins de faire des tests du style if (T is IMachin) else if (T is IBidule).
    J'avais voulu faire la même chose, du style (l'exemple est bidon mais simple):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public ConvertTodecimal<T>(T value)
    {
    ...
    }
    qui appelerait automatiquement convert.todecimal(string), convert.todecimal(double d), convert.todecimal(int i), etc. en fonction de T, mais j'avais laissé tomber.
    ಠ_ಠ

  4. #4
    Membre éprouvé Avatar de anthyme
    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 559
    Points : 1 257
    Points
    1 257
    Par défaut
    Guulh a bien compris ce que je voulais dire

    Bon snif

    Je laisse quand même le topic au cas ou quelqu'un aurait une idée

  5. #5
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par anthyme Voir le message
    Guulh a bien compris ce que je voulais dire

    Bon snif

    Je laisse quand même le topic au cas ou quelqu'un aurait une idée
    Je pensais pouvoir feinter comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    void f<T>(T value)
    {
       g(value);
    }
    void g(object obj)
    {
    ...
    }
    void g(int i)
    {
    ...
    }
    Malheureusement, f<int> n'appelle pas g(int) mais g(object) car le compilo ne sait caster T qu'en object (ou autre chose si on a défini une clause where). Le genre de différence subtile entre les templates et les generics

    Mais si quelqu'un a une solution autre qu'un switch(typeof(T).ToString()) bien crado, je suis preneur aussi.
    ಠ_ಠ

  6. #6
    Membre éprouvé Avatar de anthyme
    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 559
    Points : 1 257
    Points
    1 257
    Par défaut
    je peux pas tester pour le moment mais je viens de penser :

    peut etre avec un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fonction(objet as objet.GetType())
    ??

    Je testerai ce soir ...

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Salut,

    premiere chose, tu ne peux utiliser as qu'avec un type ref, donc pour les int ca ne marchera pas, et tu ne peux pas non plus utiliser as avec un type (variable), tu ne peux faire qu'avec un defini à la compilation ou un type parametre (dans une methode genrique) au minimum contraint sur un type reference.

    Bref pas beaucoup de solutions, a part, le "tres laid" switch sur o.GetType().ToString() , peut etre (sans certitude) aussi avec une methode dynamique, mais ca risque de pas mal complexifier le 'schmilblikk'.

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    En fait,

    on peut atteindre une partie de l'objectif grace au namespace System.Reflection... => mon préféré lol.

    disons qu'en fait tu peux énumerer les méthodes dont tu dispose et appeler celle que tu souhaite en lui fournissant le paramètre qui va avec le paramètre que tu as recut puisque tu peux extraire le type dynamique du paramètre...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Type iType = obj.GetType();
    Donc si tu énumere les méthodes dont tu dispose... tu peux appeler celle que tu veux, en détaillant les paramètres de chacune et leur types.
    Ensuite si tu vois une corrélation entre le type de ton objet et le type du paramètre tu appel la méthode en question directement.

    Attention toutefois avec cette technique.
    Si tu analyse les paramètres et que tu rencontre des types primitifs, les objets types retournés les déclarerons bien (genre avec le nom "int" par exemple).
    cependant, ton objet dont tu as récupèré le type, dans la mesure où tu l'a notifié comme object dans le prototype de la méthode aura TOUJOURS un type non primitif, meme si techniquement la donnée est primitive.

    En clair si ta méthode est : void Dispatch(object iObj);
    si tu fait Dispatch(8);
    quand tu va faire iObj.GetType();
    le Type récupéré ne portera pas le nom "int", car ce que tu récupérera c'est la représentation de l'int sous forme d'objet donc "Int32",

    heureusement il existe des cast implicites de l'un à l'autre, aussi tu pourra appeler la bonne méthode en lui fournissant le paramètre iObj sans probleme.

    Tu peux utiliser les propriétés IsEnum, IsPrimitive, pour avoir une idée de ce que tu manipule comme type, ensuite avec le nom... ou la comparaison directe
    iObj.GetType() == typeof(Int32) par exemple, fonctionne si ce que tu as dans iObj est un Int32.

    (Rappel : il ne peut exister qu'une seule et unique instance de l'objet Type par type défini dans l'assembly)

  9. #9
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    "On ne chasse pas le moustique au canon" dixit Confusius,

    or là c'est exactement ce que l'on fait en sortant la Reflexion comme arme ultime... en plus il faut savoir que ce mécanisme est relativement lent, cependant il répond en partie à tes exigences, mais bon... personnellement à moins que tu n'ai des méthodes pour des centaines de types différents... je vois pas l'intérêt d'utiliser un tel mécanisme.

    Cependant si tu veux l'améliorer, tu peux créer un dictionary
    avec comme clé le type et comme valeur, l'objet MethodInfo correspondant à la méthode la plus adéquate.

    Ensuite lors du premier lancement de la méthode quand le dictionary n'est pas iniatialisé tu l'initialise et tu énumere les méthodes à appeler et tu les injecte dans le dictionnary...
    Ensuite lors des lancemnts suivant tu entre le type d'un coté tu recoit la méthode de l'autre... et ta pu qu'a forcer l'appel par Reflexion.

  10. #10
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par cinemania Voir le message
    "On ne chasse pas le moustique au canon" dixit Confusius,

    or là c'est exactement ce que l'on fait en sortant la Reflexion comme arme ultime... en plus il faut savoir que ce mécanisme est relativement lent, cependant il répond en partie à tes exigences, mais bon... personnellement à moins que tu n'ai des méthodes pour des centaines de types différents... je vois pas l'intérêt d'utiliser un tel mécanisme.
    Un exemple simple : un webservice, sur lequel je n'ai pas la main, me renvoie des listes d'objets qui ont une plus ou moins sale tronche. Je veux, de façon générique, mettre ces objets dans des dictionnaires (ils ont tous un champ / une propriété / une méthode de type id qui nous servira de clé).
    On pourrait essayer:
    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
    Dictionary<int, T> ConvertToDico<T>(IEnumerable<T> list)
    {
        Dictionary<int, T> result = new Dictionary<int, T>();
        foreach(T item in list)
            result[getKey(item)] = item;
        return result;
    }
     
    int getKey(object item)
    {
    throw new exception("j'existe pour que ca compile mais je veux pas qu'on me lance !");
    }
    int getKey(C1 item) {return item.id; }
    int getKey(C2 item) {return item.GetIdentificationKey();}
    int getKey(C3 item) {return item.Bidule.Id; }
    Et espérer que ConvertToDico<C1>() appelle bien getKey(C1).

    Bon, en l'occurence, j'ai découvert entre temps l'existence de KeyedCollection et je me suis plus reposé la question.
    ಠ_ಠ

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    tu veux parler de KeyedByTypeCollection je suppose ?
    En effet ça semble pas mal...
    tu peux faire un truc comme ça :
    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
     
     
    public class Titi
    {
     
    public delegate void MyFunctionDelegate(object o);
     
    public void MyFunction_int(int i)
    {
    }
     
    public void MyFunction_string(string s)
    {
    }
     
    public void MyFunction_Toto(Toto t)
    {
    }
     
    public KeyedByTypeCollection<MyFunctionDelegate> MyFunctions;
     
    public void MyFunction(object o)
    {
      if (MyFunctions.ContainsKey(o.GetType()))
        MyFunctions[o.GetType()](o);
      else
        throw new NotImplementedException();
    }
     
    public Titi()
    {
      MyFunctions = new KeyedByTypeCollection<MyFunctionDelegate>();
      MyFunctions.Add(typeof(int), new MyFunctionDelegate(MyFunction_int));
      MyFunctions.Add(typeof(string), new MyFunctionDelegate(MyFunction_string));
      MyFunctions.Add(typeof(Toto), new MyFunctionDelegate(MyFunction_Toto));
    }
     
    }
    Bon, ok, c'est moche, mais conceptuellement c'est intéressant je trouve...

  12. #12
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par tomlev Voir le message
    tu veux parler de KeyedByTypeCollection je suppose ?
    Ah tiens non, je connaissais pas ça ! Intéressant Non, je parlais de KeyedCollection, une classe abstraite dont on doit juste surcharger une fonction protected GetKeyForItem(). Pratique : un Add(T item suffit), au lieu d'un relou mondico[clé] = item. Ca n'a pas de rapport direct avec le thread en fait, mais ça avait résolu mon problème. http://msdn2.microsoft.com/en-us/lib...38(vs.80).aspx

    Bon, ok, c'est moche, mais conceptuellement c'est intéressant je trouve...
    C'est un switch(GetType.ToString()) bien caché mais plus joli en effet
    ಠ_ಠ

  13. #13
    Membre éprouvé Avatar de anthyme
    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 559
    Points : 1 257
    Points
    1 257
    Par défaut
    Bonsoir !

    Je suis content que mon topic "dechaine les passions"
    J'ai corrigé une erreur dans mon premier message (ct 2 fois la même interface en entrée)

    Guulh > Je ne vois pas vraiment comment ton code peut fonctionner
    en rajoutant ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public void RegisterViewEvents(Object view)
    {
         throw new Exception("Missing RegisterViewEvents method for : " + view.GetType().ToString());
    }
    et l exception est toujours levé.

    tomlev et cinemania c'est pas mal votre solution mais je l'adapterai bien en metant dans la superclasse un methode qui récupére les methode d'event de maniere reflexive (va falloir que je me mette a jour j'ai jamais fait de reflexion en .net )

    sinon ça peut aller jusqu'a 15 types tout de même et une methode en amont qui fait des traitement sur du <t> (t) donc c'est pas vraiment inutile

    mais la on par sur du func(Object) je me demande si il n'y a pas un moyen plus direct de récuperer le type en généric tout de même ...

Discussions similaires

  1. pour se diriger vers une page web
    Par Ickou dans le forum Langage
    Réponses: 4
    Dernier message: 31/03/2006, 16h31
  2. Réponses: 8
    Dernier message: 27/02/2006, 14h28
  3. redirection vers la bonne page
    Par PAYASS59 dans le forum Langage
    Réponses: 6
    Dernier message: 30/01/2006, 11h30
  4. [EJB2.1 Entity] [CMP] Est-ce la bonne méthode ?
    Par stailer dans le forum Java EE
    Réponses: 8
    Dernier message: 20/06/2004, 19h42

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