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 :

Appel Dynamique de fonction


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Mai 2009
    Messages
    172
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 172
    Par défaut Appel Dynamique de fonction
    Bonjour à tous

    Je possède dans un string le nom d'une fonction (nom complet), toutes les fonctions sont de types void NomFonction(object sender, EventAgrs e)

    Et j'aimerais pouvoir les appeler en fonction de mes besoins (je stocke les noms dans un array) donc dynamiquement.

    J'avais testé ceci:
    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 void AppelMethode(string strParam)
      {
       // On récupère le Type de la classe elle-même
       Type oType = this.GetType();
       string strMask = "";
       // On va récupérer la liste des méthodes qui existent dans la classe 'TestReflection'
       MethodInfo[] ListMethods = oType.GetMethods();
       object objVal = null;
       // Donc pour chaque méthode :
       foreach ( MethodInfo mi in ListMethods )
       {
        // Si le nom de la méthode est égale à "Appel_" + strPAram
          // DialogResult t = MessageBox.Show(mi.Name);
        if ( mi.Name == strParam )
        {
         // Alors on 'exécute' cette méthode que l'on a trouvée
     
         mi.Invoke(null, null);
     
         break;
        }
       }
    }
    Sauf que mi.Name n'est jamais égal à strParam alors que j'ai vérifié ma fonction s'appelle bien afficher_recherche.
    Deuxième problème, il y a plus de 500 fonctions dans mon application, alors avant qu'il les teste toutes.
    Connaissant le nom de ma fonction, je ne peux pas directement l'appeler (en vérifiant au préalable qu'elle existe) sans tester toutes les fonctions de la liste.


    Merci d'avance, r0seBa

  2. #2
    Membre confirmé Avatar de thelpi
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 217
    Par défaut
    Salut,

    Pour éviter d'avoir à tout parcourir, tu dois pouvoir faire quelque chose dans ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ListMethods = oType.GetMethods().Where( method => method.Name== strParam )
    Ainsi tu parcours un nombre beaucoup plus restreint, sans soulever d'exception si la méthode avec ce nom n'existe pas.

    Pour ton problème de nom, a tu vérifié en aps à pas le contenu de mi.Name pour voir où se situe précisément la différence avec strParam ?

    @+

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    thelpi réfléchi avant d'écrire.
    ton code ne change rien au shmilblick, c'est même pire.

    Car pour pouvoir parcourir un nombre plus restreint, elle fait d'abord un passage qui vérifie TOUTES les méthode de la liste pour ne retourner finalement une énumération que de 0 ou quelques valeurs si une méthode a un nom mais plusieurs profils.
    Sais tu au moins ce que tu écrit ? les méthodes d'extensions c'est bien mais savoir ce qu'elles font c'est mieux.

    Son code a pour avantage de toutes les parcourir, mais d'exécuter à la volée celle qui correspondent au profil, sans devoir faire un second parcours, strictement inutile.
    De plus tu ne répond aucunement à sa problématique.

    Alors pour information, la Reflection tant qu'il s'agit d'obtenir des informations est très rapide, et on peut considérer que les temps sont négligeables.
    Dès lors qu'ils s'agit d'appels là par contre, c'est un drame.

    Il peut y avoir plusieurs raisons au fait que tu n'a pas obtenu de méthode qui corresponde au nom que tu as fourni. La première, le nom ne coïncide pas parfaitement, car il est sensible à la casse comme l'est C#, dans ce cas il faut faire une comparaison insensible à la casse.
    Secundo, et là c'est nettement plus grave, les méthodes que tu veux appeler sont déclarées, internal, protected ou private... par conséquent elles sont protégées et il faut lui dire explicitement que tu souhaite récupérer ces membres pour les appeler.

    Tu peux faire l'invocation d'un membre directement sur un type sans te soucier de savoir s'il est ou non disponible et récupérer l'exception.
    Type.InvokeMember(string nom, bindingflags...) regarde le profil.
    Attention, les bindings flags vont devoir ressembler à cela :

    si tu effectue l'appel sur une instance de type :
    BindingFlags.Instance | BindingFlags.Public | BindingsFlags.NonPublic

    ou si tu effectue l'appel sur un type static :
    BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic

    sur le invokemember il te faudra probablement activer l'insensibilité à la casse.

    tu peux nous donner un exemple de ce que contient strParam ?

  4. #4
    Membre confirmé
    Inscrit en
    Mai 2009
    Messages
    172
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 172
    Par défaut
    Merci pour vos réponses.

    Alors oui visiblement ma fonction était private c'est pourquoi il ne la trouvait pas. j'ai mis public, la condition est donc vraie, mais j'ai une erreur:

    L'exception System.Reflection.TargetException n'a pas été gérée
    Message="Une méthode non statique requiert une cible."
    J'ai vérifié via les variables locales, la variable mi contient:

    {Void afficher_recherche(System.Object, System.EventArgs)}" de type "System.Reflection.MethodInfo {System.Reflection.RuntimeMethodInfo}
    J'ai abandonné ton idée d'invokemember puisque non trouvée sur msdn.

    Merci

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    lol non trouvée...

    et sur visual studio jamais vous faites F1 ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    var oType = typeof(T);
    oType.InvokeMember(...);
    alors c'est normal que ca marche pas...
    Il y a également plusieurs profils à Invoke sur une methodInfo.

    là l'exception indique que vous essayez d'invoquer une méthode d'instance, sans fournir l'objet sur lequel faire l'appel... ca ne risque pas de fonctionner.

    d'où ma remarque sur le fait que c'est soit une méthode d'instance, soit une méthode statique.
    dans le cas là je penche pour une méthode d'instance, donc fournir le type d'objet est une chose, mais fournir l'objet lui même c'est encore mieux.
    donc en l'occurrence cela ressemblerais à this.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var params = new object[] { sender, new EventArgs() };
    mi.Invoke(this, params);
    Note: si c'est pour un appel ou 2, utiliser l'invocation dynamique est une bonne chose, si en revanche, c'est pour N appels avec N pouvant être très grand, ce n'est plus une technique viable en terme de performances.
    La réflexion et l'invocation dynamique de membre est une vraie plaie, surtout sur les membres privés. C'est une pure catastrophe en terme de performances, donc selon l'usage en question, il faudra peut être envisager une autre solution.

    Encore une fois tout est affaire de problème et de volumétrie. quel est le besoin exact ? la reflexion n'est pas toujours la solution non plus.

  6. #6
    Membre confirmé
    Inscrit en
    Mai 2009
    Messages
    172
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 172
    Par défaut
    Merci pour la réponse.

    Le code servira à réaliser une sorte d'historique en stockant dans un array les fonctions des "pages" à afficher.
    Et en adaptant le code que tu as donné ça semble fonctionner.

    Merci, problème résolu.

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

Discussions similaires

  1. Appel dynamique de fonction par char*
    Par Scorpi0 dans le forum C
    Réponses: 8
    Dernier message: 11/06/2008, 21h08
  2. [JavaScript] [FAQ] Appeler dynamiquement une fonction et passer une fonction en argument
    Par SpaceFrog dans le forum Contribuez
    Réponses: 0
    Dernier message: 28/05/2008, 14h48
  3. Appeler dynamiquement une fonction javascript
    Par BigDozer dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 28/05/2008, 14h41
  4. [Framework] Appel dynamique de fonctions
    Par hdd dans le forum Général Dotnet
    Réponses: 1
    Dernier message: 21/12/2006, 17h35
  5. Appel dynamique de fonctions
    Par smyley dans le forum MFC
    Réponses: 4
    Dernier message: 27/10/2005, 12h53

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