2009-09-29 4 views
28

J'ai une situation étrange où j'ai besoin d'obtenir le nom du délégué sous forme de chaîne. J'ai une méthode générique qui ressemble à ceci.Nom de l'action/délégué Func

private T Get<T>(T task, Action<T> method) where T : class 
{ 
    string methodName = method.Method.Name //Should return Bark 
} 

et je vous appelle comme ça

private void MakeDogBark() 
{ 
    dog = Get(dog, x=>x.Bark()); 
} 

Mais au lieu de voir "écorce" Je vois ce "<MakeDogBark>b__19". Il semble donc qu'il me donne le nom de la méthode qui a fait l'appel initial au lieu du nom du délégué.

Quelqu'un sait-il comment faire?

Répondre

45

Il vous donne le nom de la méthode qui est l'action du délégué. Cela vient juste d'être implémenté en utilisant une expression lambda.

Vous avez actuellement un délégué qui à tour de rôle appelle Bark. Si vous souhaitez utiliser directement Bark, vous devez créer un délégué ouvert pour la méthode Bark, ce qui peut ne pas être très simple. C'est en supposant que vous voulez vraiment l'appeler. Si vous n'avez pas besoin d'appeler, ou vous savoir qu'il sera appelé le premier argument de toute façon, vous pouvez utiliser:

private T Get<T>(T task, Action method) where T : class 
{ 
    string methodName = method.Method.Name //Should return Bark 
} 

private void MakeDogBark() 
{ 
    dog = Get(dog, dog.Bark); 
} 

Vous pourrait contourner ce en faisant le paramètre une expression tree au lieu d'un délégué, mais cela ne fonctionnerait que si l'expression lambda n'était qu'un appel de méthode.

+0

Cela a fonctionné à merveille. Je n'avais pas besoin de l'exécuter mais je devais passer le nom de la méthode à une classe qui ferait quelque chose avec. Au lieu de simplement prendre une chaîne, je voulais que le type de sécurité de l'appelant ait à me donner une vraie méthode. Comme toujours vous êtes l'homme :) – Adam

+0

@Jon Y at-il un moyen de faire de même avec une méthode générique? –

+0

@ArnabChakraborty: Vous devez également spécifier l'argument type, mais je pense que cela fonctionnerait. Je ne peux pas facilement l'essayer maintenant. –

5

Vous pouvez obtenir le nom de l'appel de méthode en faisant le paramètre une expression au lieu d'un délégué, tout comme Jon mentionné

private T Get<T>(T task, Expression<Action<T>> method) where T : class 
{ 
    if (method.Body.NodeType == ExpressionType.Call) 
    { 
     var info = (MethodCallExpression)method.Body; 
     var name = info.Method.Name; // Will return "Bark" 
    } 

    //..... 
} 
+2

Donc, vous dites qu'il serait appelé comme 'Get (x => x.DoSomething (Arg1))'? Que se passerait-il si vous vouliez simplement passer la méthode en tant que délégué de manière sécurisée mais sans l'invoquer, comme ceci 'Get (x => x.DoSomething)'? – bflemi3

+0

Oui. Essentiellement, existe-t-il un moyen de faire l'opérateur 'nameof' de C# 6 en C# 5? –

Questions connexes