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 :

[Reflexion] donner un type à T


Sujet :

C#

  1. #1
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut [Reflexion] donner un type à T
    Bonjour,

    Je suis en train de développer une librairie qui utilise à un certain moment ce type de code (très schématique) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    List<trucs> monObject = new List<trucs>();
    TransformeVar<T>(monObject);
    Je voudrais rendre une autre partie de mon code plus générique, je ne vais pas rentrer dans les détails, mais en gros : j'aimerais passer en paramètre : T

    Je voudrais rendre le code ci-dessus et ne pas être obligé de typer T en dur dans le code, j'aimerais que ce soit dynamique.

    J'ai fait quelques essais avec de la réflexion mais rien à faire... quelqu'un aurait il déjà fait ça ? ou aurait une idée ?

    En vous remerciant pour votre aide,

  2. #2
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Je suis désolé mais je ne comprends pas la question. Et je ne pense pas être le seul.

    Dans ton appel de TransformeVar, T est-il supposé représenté le type source (celui de monObject), ou un type de destination après une conversion ? Dans le premier cas il n'est pas nécessaire d'ajouter "<T>", dans le second je ne vois pas comment le programme pourrait lire dans ton esprit la conversion que tu souhaites faire.

    Bref, j'imagine que tu voulais dire tout autre chose.

  3. #3
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut
    Je me doutais que j'étais pas clair.

    Ok, donc voici clairement le truc :

    Aujourd'hui j'ai ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    public void GetClients(string JsonResult)
    { }
    Dans la librairie que je suis en train de développer, donc autant le dire : une suite de classe permettant de développer facilement du Silverlight avec PHP, j'ai à un moment donné ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     SrvClientReturnObject obj = JsonConvert.DeserializeObject<SrvClientReturnObject>(e.Result);
     
                        Type myTypeObj = ClasseAppellante.GetType();
                        MethodInfo myMethodInfo = myTypeObj.GetMethod(obj.MethodName);
     
     
                        myMethodInfo.Invoke(launcher, new object[] { obj.CustomResult });
    C'est pas mal... Dans ma méthode qui reçoit la chaine Json je peux faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public void GetClients(string JsonResult)
    { 
    List<clients> MesClients = JsonConvert.DeserializeObject<List<clients>>(JsonResult);
    }
    Ca fonctionne bien mais je voudrais aller plus loin et carrément avoir ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    public void GetClients(List<clients> mesClients)
    { 
    }
    Pour cela il faut que ma méthode qui utilise la réflexion puisse utiliser ce type en paramètre

    Alors j'ai essayé le code suivant mais qui ne marche pas bien évidemment :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     SrvClientReturnObject obj = JsonConvert.DeserializeObject<SrvClientReturnObject>(e.Result);
    
                        Type myTypeObj = ClasseAppellante.GetType();
                        MethodInfo myMethodInfo = myTypeObj.GetMethod(obj.MethodName);
    
    
    ParameterInfo info = myMethodInfo.GetParameters()[0];
    
     var objResult= JsonConvert.DeserializeObject<  info.ParameterType >(obj.CustomResult )
    
    
    
                        myMethodInfo.Invoke(launcher, new object[] { objResult });
    J'ai essayé différentes méthodes trouvées sur le net pour faire du cast dynamiquement mais rien n'y fait.

    Grâce à ce que j'ai développé j'arrive à une archi intéressante qui me permet de fonctionner à peu près comme du WCF.. Mais si je pouvais directement caster ce serait un peu la cerise sur le gâteau

  4. #4
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    En somme, tu souhaites pouvoir définir une méthode "GetClients(List<Client> clients)" et l'appeler en fournissant en argument une chaîne de caractères ?

    Tout dépend de qui doit appeler la méthode : l'appelant sera t-il un membre de la même assembly ou bien étranger à celle-ci ? En fonction de cette réponse, on peut bâtir une solution exploitant la réécriture d'assembly (via Cecil ou PostSharp par exemple) et/ou le typage dynamique (avec ou sans adaptateur).


    EDIT : Oups, faitgué, moi. Pour reprendre ton code qui ne fonctionne pas...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    //  var objResult= JsonConvert.DeserializeObject<  info.ParameterType >(obj.CustomResult );
    var deserializeMethodDefinition = typeof(JsonConvertObject).GetMethod("DeserializeObject");  // JsonConvert.DeserializeObject<>
    var deserializeMethod = deserializeMethodDefinition.MakeGenericMethod(info.ParameterType);   // JsonConvert.DeserializeObject<T>
    var objResult = deserializeMethod.Invoke(null, new object[] { obj.CustomResult });

  5. #5
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut
    Je pense qu'avec ton "MakeGenericMethod" on est pas loin..

    En fait j'ai essayé ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Type myTypeObj = launcher.GetType();
                        MethodInfo myMethodInfo = myTypeObj.GetMethod(obj.MethodName);
     
    ParameterInfo info = myMethodInfo.GetParameters()[0];
     
    var ob = Activator.CreateInstance(info.ParameterType);
     
    var monReturn = JsonConvert.DeserializeAnonymousType(obj.CustomResult.ToString(), ob  );
    Qui ne marche pas....

    Alors que bien sûr ceci fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Type myTypeObj = launcher.GetType();
                        MethodInfo myMethodInfo = myTypeObj.GetMethod(obj.MethodName);
     
    ParameterInfo info = myMethodInfo.GetParameters()[0];
     
    // fonctionne pas
    //var ob = Activator.CreateInstance(info.ParameterType);
     
    // fonctionne
    var ob = new List<clients>();
     
    var monReturn = JsonConvert.DeserializeAnonymousType(obj.CustomResult.ToString(), ob  );
    Ton code part sur la généricité de "JsonConvert" ou je me trompe ?

    En fait je suis pas loin : sauf que le Activator ne me donne pas le bon type (j'ai une exception qui me le dit) ! alors que le paramètre est bien du bon type.. C'est la ou ça coince

  6. #6
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    C'est étrange, Activator fonctionne en principe très bien avec les types génériques, tu es certain que info.ParameterType est bien du type "List<Client>" ?
    Sinon, quelle exception et à quel endroit ?

    A part ça, concernant le code que j'ai donné, il faut distinguer les "définitions de méthodes génériques" (MethodInfo.IsGenericMethodDefinition) et les "methodes génériques" (MethodInfo.IsGenericMethod). Quand tu définis JsonTruc.Convert<T> dans JsonTruc, tu écris une définition. Quant tu l'invoques avec un paramètre "JsonTruc.Convert<String>" tu invoques en fait une méthode générique bâtie depuis la définition.

    Mon code fait exactement cela :il récupère la définition, demande la construction d'une méthode générique avec le paramètre spécifié et l'invoque.

  7. #7
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut
    Malheureusement je pense que ça vient de JsonConvert (issue de la librairie JSON.NET) ...

    J'ai une exception sur le invoke ou il me dit qu'il ne peut caster le :

    Collections.Generic List 1 ' Newton.Json.Linq.JArray

    en

    Collections.Generic List 1 ' Mapping.clients

    Je crois que c'est mort...

    Merci beaucoup pour ton aide, je garde ton code sous le coude et je vois ce que je peux faire ces jours ci...

    Bonne nuit !


    EDIT : oui le Parameter est du bon type mais c'est le DeserializeAnonymousType qui merde et me renvoie cette collection de JArray

  8. #8
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Mais non, le problème est tout bête : je suis allé regarder la doc sur JsonConvert.DeserializeAnonymousType. Il s'agit en réalité d'une méthode générique. Dans un cas ton "var ob" désigne un "object", dans l'autre un "List<Client>". En conséquence dans un cas tu appelles "JsonConvert.DeserializeAnonymousType<Object>" et dans l'autre "JsonConvert.DeserializeAnonymousType<List<Client>>".

    Il faut simplement que tu appliques la manip que je t'ai donnée plus haut avec MakeGenericMethod à JsonConvert.DeserializeAnonymousType.

  9. #9
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut
    Bon... La je suis mort mais j'essaye dès que je peux.

    Faut que je comprenne ce MakeGenericMethod, ça m'échappe un peu pour le moment.

    Merci

  10. #10
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Imagine une méthode M définie comme : Machin.Truc<T>(T arg);

    Tu as l'impression que si tu invoques "Machin.Truc("abc")" tu invoques M, pas vrai ? Faux ! En réalité le framework crée à la volée (lors du Jit-age) une méthode M1 bâtie depuis M grâce à MakeGenericMethod. M n'est jamais invoquée, elle ne peut pas être exécutée.

    M1 est définie comme Machin.Truc`1(String arg).

  11. #11
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut
    Ok, après avoir dormi tout devient plus clair

    J'ai bien compris tes explications et ton code...

    C'est à 2 doigts de fonctionner sauf que j'ai une exception qui me type que c'est ambigue.

    Je pense que c'est dû au fait que dans JsonConvert il y a :
    DeserializeObject et DeserializeObject<>

    Donc le souci est la :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    var deserializeMethodDefinition = typeof(JsonConvertObject).GetMethod("DeserializeObject");
    J'ai essayé ceci qui ne fonctionne pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    var deserializeMethodDefinition = typeof(JsonConvertObject).GetMethod("DeserializeObject<>");
    Oui bon, quitte à faire ça autant rien faire

    Tu aurais une idée ?
    J'ai essayé aussi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typeof(JsonConvertObject).GetMethods("DeserializeObject");
    Mais ça le fait pas non plus.

    Je te remerci encore pour ton aide, j'ai appris pleins de choses et on est vraiment pas loin du compte.

  12. #12
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Je t'en prie.
    Sinon ce cas-ci est toujours un peu ennuyeux, il faut utiliser cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typeof(JsonConvertObject).GetMethods().First(m => m.IsGenericMethodDefinition && m.Name == "DeserializeObject");

  13. #13
    Membre Expert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 056
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 056
    Par défaut
    J'ai pas tout compris à l'histoire mais si tu veux invoquer la méthode générique il faut bien lui passer le type non?
    http://msdn.microsoft.com/fr-fr/libr...(v=vs.95).aspx


    Edit: je crois que je divague

  14. #14
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut
    @DonQuiche : j'étais en train de faire un code similaire mais dans le mien j'avais ma liste de méthodes et je faisais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    maListeMethodes[30]
    En debug j'ai pu déterminer que ma méthode voulue était la 30ème dans la liste... Pas terrible

    Bref, que ce soit ton code ou le mien, ça ne plante pas mais ça fait rien du tout...

    La classe appelante est pourtant la bonne, tout est ok...

  15. #15
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut
    Ca marhe !!

    Désoooolé pardon !

    En fait j'ai une seconde invocation sur la classe appelante qui suit ce code et je l'avais commenté.

    Merci ENORMEMENT pour ton aide ! c'est nickel.

  16. #16
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Ma foi, content que ce soit résolu.

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

Discussions similaires

  1. importance de donner le bon type
    Par Lorenzo77 dans le forum C#
    Réponses: 5
    Dernier message: 21/08/2008, 15h01
  2. [Forms10g] Donner Parametre type text item Procedure
    Par sterix92 dans le forum Forms
    Réponses: 6
    Dernier message: 20/05/2007, 13h48
  3. Réponses: 5
    Dernier message: 29/09/2006, 17h17
  4. [c#][Reflexion] Obtenir le type d'un generic
    Par shwin dans le forum Windows Forms
    Réponses: 12
    Dernier message: 03/08/2006, 16h34
  5. reflexion et type de retour des méthodes
    Par money mark dans le forum Langage
    Réponses: 2
    Dernier message: 09/04/2006, 18h46

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