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 :

Invocation d'une méthode d'une classe à partir d'une autre classe.


Sujet :

C#

  1. #1
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 31
    Points : 25
    Points
    25
    Par défaut Invocation d'une méthode d'une classe à partir d'une autre classe.
    Bonjour,

    Je travaille sur un projet assez conséquent et je voudrais effectuer une modification importante.

    A plusieurs endroits du projet, il y a des méthodes qui appellent d'autres méthodes (EasyObject qui elles appellent des procédures stockées).

    L'appel de ces méthodes se fait généralement de cette manière :

    NOM_CLASSE.NOM_METHODE(argument1, argument2, ...);

    Ces méthodes sont toujours statiques.

    Voilà ce que je souhaiterai faire (j'ai essayé avec les délégués mais je m'y perds un peu) :

    Je voudrais pouvoir créer une sorte de classe qui gère toutes ces méthodes sans les connaitre à l'avance afin de pouvoir en gérer les exceptions, y ajouter des logs, etc...
    Cela m'évitera de mettre un try..catch de toutes les exceptions possibles sur chaque méthode sachant que la plupart on les mêmes erreurs et vont générer les mêmes logs (d'autant plus que c'est une zone rouge du code que je ne peux pas vraiment modifier à ma guise car géré par une autre partie de l'entreprise).

    Ensuite, on appelant ma classe, on exprimerai le nom de la classe, le nom de la méthode et les arguments voulus et ma classe renverrai si ça s'est bien déroulé ou non.
    Derrière, cette classe serait donc capable de faire tout un tas d'opérations que je souhaite y ajouter.

    Une sorte de classe de contrôle des méthodes.

    Je sais pas trop comment cela se présenterai au final mais il faudrait que ça ressemble à quelque chose du genre :
    MaClasse mc = new MaClasse();
    mc.AppelMéthode(NOM_CLASSE.NOM_METHODE(argument1, argument2, ...));


    Je travaille dessus en ce moment mais je ne m'en sort pas alors si quelqu'un a des idées, je vous en remercie.

  2. #2
    Membre régulier
    Inscrit en
    Juin 2009
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 100
    Points : 94
    Points
    94
    Par défaut
    Salut,

    Ton problème n'es pas ultra simple mais c'est effectivement possible en utilisant les Assembly

    Voici un petit exemple illustrant mes propos.
    La classe MaClasse contenue dans le namespace MonNamespace :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    namespace MonNamespace
    {
        public class MaClasse
        {
            public static void Aff()
            {
                System.Console.Out.WriteLine("MaClasse.Aff");
            }
        }
    }
    Tu vas pouvoir invoquer la method static Aff de MaClasse en réalisant les opération suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Assembly ass = Assembly.GetAssembly(typeof(MonNamespace.MaClasse));
    Type t2 = ass.GetType("MonNamespace.MaClasse");
     
    t2.InvokeMember("Aff", BindingFlags.InvokeMethod, null, null, null);
    Ici, on charge l'espace de nom contenant MaClasse dans ass. Ensuite on répcupère la classe MaClasse à travers ass.
    A l'aide de la méthode invokeMember on appelle la méthode Aff de la classe MaClasse.
    Tu peux, à partir de t2 effectuer toute les opération disponible pour cette classe (instanciation, appel de méthodes statiques ou non...)

    Pour plus de précision regarde la doc pour Assembly et Type :

    http://msdn.microsoft.com/fr-fr/libr....assembly.aspx
    http://msdn.microsoft.com/fr-fr/libr...stem.type.aspx

    Bobbledople

  3. #3
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 31
    Points : 25
    Points
    25
    Par défaut
    Merci pour cette réponse.

    Je vais essayer de m'en sortir avec cette méthode, je pense que ça devrait marcher.

    Juste un truc...
    Avec cette façon de faire, cela voudra dire qu'il faudra appeler les méthodes dans le code avec des string j'imagine.
    Quelque chose de générique donc : ("nom de la méthode", arguments[]) qui renvoie un object. Ca va faire peu propre je trouve.

    J'avais aussi pensé à rajouter des EventHandler à l'invocation de la méthode ce qui m'éviterai carrément d'y toucher mais je ne sais pas non plus si c'est possible.

  4. #4
    Membre régulier
    Inscrit en
    Juin 2009
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 100
    Points : 94
    Points
    94
    Par défaut
    Effectivement sans etre "sale" cette technique est peu sécuritaire dans le sens où les erreurs d'invocation ne sont repérées qu'à l'execution, ce qui veut dire beaucoup de test pour debugguer :p

    Peut-être existe-t-il une autre façon plus propre de faire ceci mais pas à la connaissance.

    Ceci dit l'utilisation des assembly peut-etre assez prise de tête (je sais que je me suis pris la tête :p), il suffit de bien regarder les spécifications et nottament celle de la methode InvokeMethod et je trouve que msnd est plutôt bien fait dans ce sens.

    Bon Courage

  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
    Hum, y'a plus simple à mon avis.

    Par exemple :

    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
    U TryCatcherMethode<T, U>(Converter<T, U> methode, T argument)
    {
      try
      {
        return methode(argument);
      }
      catch(Exception exception)
      {
        Loguer.Cette(exception);
        throw; // ou pas :)
      }
    }
     
    // appelé ensuite ainsi :
    private int GetMachinfromBidule(string s) { ... }
    int i = TryCatcherMethode(GetMachinfromBidule, "haha");
    enfin bref on tire juste profit de la facilité avec laquelle les méthodes peuvent être manipulées en C#.
    ಠ_ಠ

  6. #6
    Membre régulier
    Inscrit en
    Juin 2009
    Messages
    100
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 100
    Points : 94
    Points
    94
    Par défaut
    En effet cette solution est peut-etre même plus propre étant donnée que plus d'erreur sont repérés à la compilation.
    Les assembly permettent plus d'opération mais dans le cas de méthode statique celle de guulh est certainement plus simple.
    J'ai une question cependant (parce que ça m'interesse maintenant :p), comment ferait tu pour générer plusieurs arguments? Y a-il une façon d'éviter de surcharger la méthode TryCatcherMethode avec deux, trois, quatre, ... arguments? Avec un tableau de T peut-être?

  7. #7
    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
    Avec plusieurs arguments, on peut ruser, en créant une méthode anonyme qui n'en aurait qu'un.

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class A
    {
      // la méthode qu'on va trycatcher
      public int GetTrucMuche(string s, double d, UneEnum e) { ... }
    }
     
    void f()
    {
      string arg1 = "haha";
      double arg2 = 3.2;
      UneEnum arg3 = UneEnum.Machin;
      A a = new A();
      int result = TryCatcherMethode(delegate(A a) { return a.GetTrucMuche(arg1, arg2, arg3); });
    }
    Bref tu génères une méthode anonyme qui va bien.
    ಠ_ಠ

  8. #8
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 31
    Points : 25
    Points
    25
    Par défaut
    Merci Guulh !

    J'avoue que travailler avec les Assembly, c'est marrant mais ça fait un peu peur :o

  9. #9
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 31
    Points : 25
    Points
    25
    Par défaut
    Après mes premiers essais, je fais une petite correction si je puis me permettre. Je rajoute <string, int> en types à la méthode TryCatcherMethode au moment de l'appel à la fin pour éviter une erreur de compilation.

    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
    U TryCatcherMethode<T, U>(Converter<T, U> methode, T argument)
    {
      try
      {
        return methode(argument);
      }
      catch(Exception exception)
      {
        Loguer.Cette(exception);
        throw; // ou pas :)
      }
    }
     
    // appelé ensuite ainsi :
    private int GetMachinfromBidule(string s) { ... }
    int i = TryCatcherMethode<string, int>(GetMachinfromBidule, "haha");

    Par contre, il se trouve alors j'ai encore un soucis. Ca fonctionne à tous les coups sauf dans le cas d'une méthode sans argument ou qui ne renvoie rien.

    En effet, je peux pas invoquer TryCatcherMethode de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    private void FaireMachinTruc(string s) { ... }
    TryCatcherMethode<string, void>(FaireMachinTruc, "haha");
    Peut-être qu'il y a juste un truc que je n'ai pas compris ?

  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
    Faut adapter un peu, pour les méthodes sans argument ni retour :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    delegate void FonctionQuiFaitRien();
    void TryCatcherMethode(FonctionQuiFaitRien fonction)
    {
      try
      {
        fonction();
      }
      catch(Exception exception)
      {
        Loguer.Cette(exception);
        throw; // ou pas :)
      }
    }
    ಠ_ಠ

  11. #11
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 31
    Points : 25
    Points
    25
    Par défaut
    Ok merci.

    J'avoue que j'ai juste du mal à comprendre l'utilisation de Converter.
    "Converter<T ,U> methode" converti l'argument en la valeur de retour ?
    J'avoue que je ne suis pas.

    Pourquoi ce genre de truc ne fonctionne pas ? :
    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
     
    U TryCatcherMethode<T, U, V>(V methode, T argument)
    {
      try
      {
        return methode(argument);
      }
      catch(Exception exception)
      {
        Loguer.Cette(exception);
        throw; // ou pas :)
      }
    }
     
    // appelé ensuite ainsi :
    private int GetMachinfromBidule(string s) { ... }
    int i = TryCatcherMethode<string, int>(GetMachinfromBidule, "haha");

  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
    Alors, pour en savoir plus, il faut se documenter sur les delegate

    Un delegate est caractérisé par une signature de fonction. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // on définit un type délégué, que l'on nomme XYZ
    delegate void MonTypeDelegue(int i);
    class A
    {
      public void UneMethode(int x) { ... }
      public void UneAutreMethode(string s) { ... }
      void f()
      {
        MonTypeDelegue x = this.UneMethode; // ok, parce que UneMethode a la bonne signature
        MonTypeDelegue y = this.AutreMethode; //  pas OK, la méthode a pas la bonne signature
      }
    }
    En plus, les delegate permettent d'utiliser les generics : tu peux donc écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    delegate void MonTypeDelegue<T>(T arg1, string arg2);
    par exemple.

    Au dessus, j'avais utilisé Converter<T, U> parce que c'est un type de délégué déjà défini dans le framework.

    Pourquoi ce genre de truc ne fonctionne pas ? :
    Parce que le compilo doit savoir statiquement si l'appel "return methode(argument)" est correct : pour ça, il faut que ta méthode de type V prenne un argument de type T et renvoie un U. Ce qui n'est le cas que si on dit au compilo que la méthode a pour signature "U methode(T arg)".
    ಠ_ಠ

  13. #13
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 31
    Points : 25
    Points
    25
    Par défaut
    D'accord merci. Je crois que je commence à comprendre

    Même si je pense que je vais garder votre méthode, j'ai pensé à faire d'une toute autre manière. Voici le truc que j'avais pensé faire :
    J'ai trouvé dans la documentation msdn qu'on pouvais récupérer tout un tas d'informations grâce à deux classes :
    - MethodInfo
    - MethodBase
    Toutes deux on une méthode appelée Invoke qui permet d'invoquer la méthode en question.

    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
     
    public static T TryCatcherMethodeStatique<T>(MethodInfo mi, object[] parametres)
    {
    	try
    	{
    		return (T) mi.Invoke(null, parametres);
    	} 
    	catch (Exception exception)
    	{
    		Exception exceptionMethode = exception.GetBaseException();
    		Logs.error(exceptionMethode.Message);
    		throw;
    	}
    }
     
    public static T TryCatcherMethode<T>(MethodInfo mi, object instance,object[] parametres)
    {
    	try
    	{
    		return (T)mi.Invoke(instance, parametres);
    	} 
    	catch (Exception exception)
    	{
    		Exception exceptionMethode = exception.GetBaseException();
    		Logs.error(exceptionMethode.Message);
    		throw;
    	}	
    }
    Alors, vous en pensez quoi ?

  14. #14
    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
    Passer par la réflexion est aussi tout à fait possible, bien sûr Mais c'est bien moins performant ; et de plus, à moins que je ne me trompe, il faut passer par le nom de la méthode sous forme de chaîne de caractère (un truc du style typeof(Machin).GetMethod("LeNomdeLaMéthode").

    Donc si un jour la méthode est renommée, le code continuera à compiler, mais tu auras une erreur à l'exécution.
    ಠ_ಠ

Discussions similaires

  1. Réponses: 2
    Dernier message: 29/10/2013, 12h19
  2. Appel d'une méthode d'une autre classe à partir d'un actionListener
    Par bisouJava dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 31/10/2011, 09h05
  3. Réponses: 3
    Dernier message: 20/04/2009, 09h13
  4. Réponses: 6
    Dernier message: 12/02/2008, 14h56
  5. Réponses: 12
    Dernier message: 07/11/2007, 00h53

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