Appel dynamique de fonction

Appel dynamique de fonction - C#/.NET managed - Programmation

Marsh Posté le 16-11-2007 à 15:53:53    

Bonjour,
 
Dans un script C#, j'aimerais pouvoir appeler dynamiquement une fonction c'est à dire, que la fonction qui sera appelée dépendra d'une variable. Est-ce que c'est possible et si oui, je fais comment ?
 
Exemple :
private void fonction_principale() {
fonction_[variable]() // si la variable vaut titi je lance fonction_titi, si la variable vaut toto je lance fonction_toto
}
private void fonction_titi () {
}
private void fonction_toto () {
}
 
(merci d'avance)

Reply

Marsh Posté le 16-11-2007 à 15:53:53   

Reply

Marsh Posté le 16-11-2007 à 16:03:28    

virtual

Reply

Marsh Posté le 23-11-2007 à 11:49:45    

what ?

Reply

Marsh Posté le 23-11-2007 à 12:16:08    

STFW

Reply

Marsh Posté le 27-11-2007 à 10:12:01    

ou delegate... (plus clean encore :p)


---------------
VA APPRENDRE ET REVIENS QUAND TU SAIS, SINON ABSTIENT TOI C'EST UN GRAND CONSEIL QUE JE TE DONNE... TU ES INCOMPÉTENT ET C'EST UNE RÉALITÉ, TU N'AS RIEN A FAIRE ICI FAUT S'Y CONNAITRE ... -Jojo1998 - RIP - http://tinyurl.com/qc47ftk
Reply

Marsh Posté le 28-11-2007 à 09:28:51    

ixemul a écrit :

ou delegate... (plus clean encore :p)


ou pas

Reply

Marsh Posté le 29-11-2007 à 00:50:52    

hal9100 a écrit :

Bonjour,
 
je ne comprend pas votre message mais a partir de ce que j'ai lit je peut donne une reponse :
 
private void fonction_principale( char *Mot) {  
(Mot=="titi" )?fonction_titi():fonction_toto(); // avec le mot Mot prendre "titi" ou une autre chaine.
}  
private void fonction_titi () {  
}  
private void fonction_toto () {  
}  
 
 
(merci d'avance)


Reply

Marsh Posté le 29-11-2007 à 10:28:54    

Il demande pas plutot la Reflection ?
 
Edit : Ha je savais que j'avais ça quelque part...
Le problème avec la solution de compilateur_c, c'est le jour où tu rajoutes une 3eme méthode...
Au moins, là, tu restes assez indépendant de l'évolution de ton code appelant.
 

Code :
  1. using System.Reflection;
  2. public class TestReflection
  3. {
  4.  public TestReflection()
  5.  {
  6.  }
  7.  // Méthode qui va choisir quelle fonction tu veux appeler
  8.  public string AppelMethode(string strParam)
  9.  {
  10.   // On récupère le Type de la classe elle-même
  11.   Type oType = this.GetType();
  12.   string strMask = "Appel_";
  13.   // On va récupérer la liste des méthodes qui existent dans la classe 'TestReflection'
  14.   MethodInfo[] ListMethods = oType.GetMethods();
  15.   object objVal = null;
  16.   // Donc pour chaque méthode :
  17.   foreach ( MethodInfo mi in ListMethods )
  18.   {
  19.    // Si le nom de la méthode est égale à "Appel_" + strPAram
  20.    if ( mi.Name.ToUpper().Equals(strMask.ToUpper() + strParam.ToUpper() ) )
  21.    {
  22.     // Alors on 'exécute' cette méthode que l'on a trouvée
  23.     // On sait qu'elle retourne "quelqu'chose". Donc on récupère ce quelque chose
  24.     objVal = mi.Invoke(this, null);
  25.     // On sort de la boucle foreach
  26.     break;
  27.    }
  28.   }
  29.   // Si on a rien trouvé, parce que objVal est resté null
  30.   // Tu fais ce que tu veux. Moi j'exceptionne.
  31.   if ( objVal == null )
  32.    throw new Exception("C'est la fin du monde..." );
  33.   // Sinon, ben je retourne la valeur string du résultat
  34.   return objVal.ToString();
  35.  }
  36.  public string Appel_Non()
  37.  {
  38.   return "NON";
  39.  }
  40.  public string Appel_Oui()
  41.  {
  42.   return "OUI";
  43.  }


 
Et quelque part, tu as un code :

Code :
  1. ...
  2. TestReflection tr = new TestReflection();
  3. ...
  4. switch ( qqch à vérifier )
  5. {
  6.     case 1:
  7.         tr.AppelMethode("Oui" );
  8.         break;
  9.     case 2:
  10.         tr.AppelMethode("Non" );
  11.         break;
  12.     default:
  13.         tr.AppelMethode("Oui" );
  14.         break;
  15. }


Message édité par Xas le 29-11-2007 à 23:42:41
Reply

Marsh Posté le 29-11-2007 à 14:03:48    

Belle usine à gaz, très bon conseil pour un débutant.

Reply

Marsh Posté le 30-11-2007 à 00:07:20    

Voilà, j'ai réediter, et j'ai mis des commentaires, et un exemple d'utilisation.
Usine à gaz ? La vache, je suis vexé sur ce coup. Une seule méthode avec un seul foreach...
 
Le mec veut appeller dynamiquement une méthode. C'est, à mon avis, une des meilleures solutions. Propre, facilement maintenable, et un bon début pour comprendre la reflection .NET.
 
Maintenant, si sous pretexte qu'il est débutant, on va lui filer une solution de merde, c'est vraiment n'importe quoi.
 
On lui offre une bonne solution pour son problème.
C'est aussi à lui de faire des efforts pour comprendre. La science .NET et programmation, ça tombe pas dessus. Faut travailler.
On est pas ici juste pour donner le code qui va fonctionner, et puis c'est tout, merci, au revoir. Si ? Ha bah désolé, je me suis trompé d'endroit, je ne dirais plus rien.
Qu'il reste ignorant, alors.


Message édité par Xas le 30-11-2007 à 00:07:32
Reply

Marsh Posté le 30-11-2007 à 00:07:20   

Reply

Marsh Posté le 30-11-2007 à 14:03:22    

Je trouve quand mêmme plus simple de faire ça...
 

Code :
  1. public interface ITruc
  2. {
  3.    void FaireQuelqueChose();
  4. }
  5.  
  6. public static class Truc
  7. {
  8.   ITruc CreateTruc(string value)
  9.   {
  10.      switch (value)
  11.      {
  12.         case "titi":
  13.            return new Titi();
  14.         case "toto":
  15.            return new Toto();
  16.         default:
  17.            throw new Exception("Paramètre incorrect" );
  18.      }
  19.    }
  20. }
  21.  
  22. public class Titi : ITruc
  23. {
  24.   private string msg = "Titi";
  25.  
  26.   public Titi()
  27.   {
  28.      // Construteur
  29.   }
  30.  
  31.   public void FaireUnTruc()
  32.   {
  33.      Console.WriteLine(msg);
  34.   }
  35. }
  36.  
  37. public class Toto : ITruc
  38. {
  39.   private string msg = "Toto";
  40.  
  41.   public Toto()
  42.   {
  43.      // Construteur
  44.   }
  45.  
  46.   public void FaireUnTruc()
  47.   {
  48.      for (int i = 0; i < 10; i++)
  49.      {
  50.         Console.WriteLine(string.Format("{0} - {1}", msg, i);
  51.      }
  52.   }
  53. }


 
Ensuite t'as juste à faire :
 

Code :
  1. ITruc t1, t2;
  2.  
  3. t1 = Truc.CreateTruc("toto" );
  4. t2 = Truc.CreateTruc("titi" );
  5.  
  6. t1.FaireUnTruc();
  7. t2.FaireUnTruc();


 
(ça rejoint le "virtual", sauf que je passe par une interface)


Message édité par MagicBuzz le 30-11-2007 à 14:04:03
Reply

Marsh Posté le 30-11-2007 à 15:13:16    

J'ai du mal a comprendre ta réponse ou celle du "virtual".
De la maniere dont j'ai lu la question de hal, il a un soucis d'appel sur une liste de méthode qui ont le même préfixe. L'appel à la bonne méthode dépend du suffixe "en test".
 
Du coup je vois très mal en quoi ta solution est plus simple (je ne dis pas qu'elle est mauvaise, là je parle de simplicité)
 
Si je suis allé trop loin dans mon interpréation, alors la question serait tout simplement "j'ai plusieurs fonctions, comment je fais pour en appeller une ou l'autre suivant un test ?"


---------------
H. - 48h en fiat et j'ai déjà perdu la maitrise de mon argent
Reply

Marsh Posté le 30-11-2007 à 16:36:37    

Xas a écrit :

J'ai du mal a comprendre ta réponse ou celle du "virtual".
De la maniere dont j'ai lu la question de hal, il a un soucis d'appel sur une liste de méthode qui ont le même préfixe. L'appel à la bonne méthode dépend du suffixe "en test".
 
Du coup je vois très mal en quoi ta solution est plus simple (je ne dis pas qu'elle est mauvaise, là je parle de simplicité)
 
Si je suis allé trop loin dans mon interpréation, alors la question serait tout simplement "j'ai plusieurs fonctions, comment je fais pour en appeller une ou l'autre suivant un test ?"


Je pense que c'est nous qui sommes allé plus loin que toi dans l'analyse de la question ;)
 
En gros, Hal veut fait un truc pourri directement hérité de PHP ou JS.
Le genre de truc qui est plantogène et piratogène à souhait.
 
Le but du jeu ici, c'est en fonction d'un paramètre, lancer une fonction spécifique, dans un cadre commun.
 
Le fait de créer une interface et des classes dérivées (ou une classe générique avec une méthode virtuelle, et des classes qui redéfinissent cette méthode) permet dont de produit le même effet : on instancie différentes classe héritées selon le critère en question, et on ne les manipule que via une déclaration de l'interface/classe générique, et on appelle la méthode de base, dont le comportement est surchargé au niveau de la classe fille, qui dépend du paramètre.
 
Ceci ne répond donc pas réellement à la question initiale, mais donne un moyen propre d'obtenir le même résultat.
 
Genre tu me demandes dans quel direction est New York. Moi je te colle dans un RER en destination de Charles de Guaule pour que tu prennes un avion. Je peux te dire que c'est à l'ouest sans t'indiquer qu'il y a un océan à traverser, mais ce serait criminel... Là c'est pareil ;)

Reply

Marsh Posté le 30-11-2007 à 21:20:57    

Je plussoie sur le fait que la reflection semble la meilleure piste

Reply

Marsh Posté le 03-12-2007 à 10:00:25    

dkomputer a écrit :

Je plussoie sur le fait que la reflection semble la meilleure piste


 
Non...  
 
Absolument pas...
 
La refelxion est beaucoup trop dangereuse
 
La solution avec delegate, qui rappelons le est exactement définie pour ce genre de chose est plus simple, totalement protégée des effets de bords et beaucoup plus souple:
 

Code :
  1. private delegate void appelFonction();
  2. private appelFonction  func;
  3. public void dispatch(string v)
  4. {
  5.   switch(v)
  6.   {
  7.     case "Toto":
  8.       func = new appelFonction(toto);
  9.       break;
  10.     case "Titi":
  11.       func = new appelFonction(titi);
  12.       break;
  13.     default:
  14.       throw new Exception("Fonction inexistante" );
  15.   }
  16.   func();
  17. }
  18. private void toto()
  19. {
  20.   Console.WriteLine("toto" );
  21. }
  22. private void titi()
  23. {
  24.   Console.WriteLine("titi" );
  25. }


 
Piqure de rappel, les delegate peuvent être assimilés à des pointeurs sur fonctions, ce qui, le cas présent permet de définir sur quel fonction notre delegate pourra pointer.
 
Astuce [:icon3], il est même possible de "Cumuler" les appels de fonction avec quelque chose du style:
 

Code :
  1. func = new appelFonction(toto);
  2. func += new appelFonction(titi);
  3. func();


 
 
Ensuite, je suis parfaitement d'accord avec Magibuzz sur ce point :
 
 

Citation :


En gros, Hal veut fait un truc pourri directement hérité de PHP ou JS.  
Le genre de truc qui est plantogène et piratogène à souhait.  
 


Message édité par ixemul le 03-12-2007 à 10:02:00

---------------
VA APPRENDRE ET REVIENS QUAND TU SAIS, SINON ABSTIENT TOI C'EST UN GRAND CONSEIL QUE JE TE DONNE... TU ES INCOMPÉTENT ET C'EST UNE RÉALITÉ, TU N'AS RIEN A FAIRE ICI FAUT S'Y CONNAITRE ... -Jojo1998 - RIP - http://tinyurl.com/qc47ftk
Reply

Marsh Posté le 03-12-2007 à 10:22:36    

Grmpf.
 
Ah oui, j'avais complètement oublié cette méthode.
Effectivement, c'est à 100% mieux que virtual/interface. Ca se rapproche du fonctionnement des méthodes utilisant la réflexion, mais de façon propre : on sait à l'avance comment ça va se comporter, ce qui n'est pas le cas avec la réflection. :jap:

Reply

Marsh Posté le 03-12-2007 à 10:50:37    

Etant fanboy de la reflection, je m'incline devant la solution de ixemul, plus intéressante.
Mais je reste dubitatif sur la dernière affirmation de MagicBuzz..
 
Sinon j'aurais du faire du php dans le passé, vu que je suis le seul à pas avoir compris de quoi s'inspire hal...

Message cité 3 fois
Message édité par Xas le 03-12-2007 à 10:50:46
Reply

Marsh Posté le 03-12-2007 à 11:24:06    

Xas a écrit :

Etant fanboy de la reflection, je m'incline devant la solution de ixemul, plus intéressante.
Mais je reste dubitatif sur la dernière affirmation de MagicBuzz..


 
Tu crées une fonction "Appel_truc", sans chercher à savoir si elle est nommée "truc", "Appel_truc" ou "machin_chose".
Genre tu fais de la TMA et t'as autrechose à foutre que de relire 25 Mo de code pour savoir si créer une méthode risque de tout foutre par terre (puisque dans du code bien écrit, c'est pas cencé)
 
Maintenant, avec ton exemple, tu appelles "AppelFunction" en passant "truc" en paramètre.
Et zou ! Ca te lance ta nouvelle méthode.
Mais t'avait pas forcément envie de pouvoir la lancer de la sorte... Donc ni toi aujourd'hui qui écrit le code, ni le gars qui repasse derrière, ne peuvent prévoir tous les effets de bord de ton code. Et pire, c'est avec ce genre de code qu'on trouve dses exploit.
 
Par exemple, si j'appelle "AppelFunction" non pas avec "Truc", mais "@@@@@@FonctionDangereuse" avec les "@" un caractère utilisant une exploit qui va effectuer un "backspace" lors d'une concaténation de chaîne, alors je peux lancer "FonctionDangereuse" malgré ton test. Y'a pas à tortiller, c'est dangereux... Et ça, tant qu'un exploit n'aura pas été trouvé, tu seras incapable de prévoir ton code.
 
Avec le delegate, tout ces trucs ne peuvent pas arriver.
Le seul "hack" possible, c'est d'aller modifier le code compilé afin de modifier les valeurs des pointeurs sur toto et titi afin de lancer d'autres fonction.
Mais sans ça, aucune exploit n'est utilisable pour, et tout modification de code reste sous contrôle : c'est pas parceque je crée une fonction "truc" que j'ai un risque d'avoir ma fonction appelée "par le saint esprit".


Message édité par MagicBuzz le 03-12-2007 à 11:26:37
Reply

Marsh Posté le 03-12-2007 à 11:25:47    

Xas a écrit :

Sinon j'aurais du faire du php dans le passé, vu que je suis le seul à pas avoir compris de quoi s'inspire hal...


 
Ben en PHP tu peux faire un truc du genre (syntaxe mise à part) :
 

Code :
  1. function AppelFct($fctname)
  2. {
  3.     $$fctname();
  4. }


=> Ca appelle la fonction qui a le nom de "$fctname".
 


Message édité par MagicBuzz le 03-12-2007 à 11:26:23
Reply

Marsh Posté le 03-12-2007 à 12:42:22    

Xas a écrit :

Etant fanboy de la reflection, je m'incline devant la solution de ixemul, plus intéressante.
Mais je reste dubitatif sur la dernière affirmation de MagicBuzz..
 
Sinon j'aurais du faire du php dans le passé, vu que je suis le seul à pas avoir compris de quoi s'inspire hal...


 
Ha mais moi aussi je suis un fan de la reflexion, mais je prefere l'utiliser pour des algos un peu plus obscurs [:rhetorie du chaos]


---------------
VA APPRENDRE ET REVIENS QUAND TU SAIS, SINON ABSTIENT TOI C'EST UN GRAND CONSEIL QUE JE TE DONNE... TU ES INCOMPÉTENT ET C'EST UNE RÉALITÉ, TU N'AS RIEN A FAIRE ICI FAUT S'Y CONNAITRE ... -Jojo1998 - RIP - http://tinyurl.com/qc47ftk
Reply

Marsh Posté le 05-12-2007 à 12:55:20    

Merci de vous être acharnés à ce point sur mon problème, ça fait plaisir de se sentir épaulé dans la détresse.
 
L'ennui c'est qu'avec les kilos de code que je bricole tous les jours, je sais même plus pour quelle raison j'avais posé cette question.

Reply

Marsh Posté le 05-12-2007 à 12:56:19    

Mais je vais retrouver

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed