2009-09-29 15 views
28

デリゲートの名前を文字列として取得する必要がある私は奇妙な状況があります。私はこのような一般的な方法を持っています。アクション/ Funcデリゲートの名前を取得

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

と、私はこの

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

のようにそれを呼び出していますしかし、その代わりに "バーク" を見ての私は、この"<MakeDogBark>b__19"を参照してください。だから、それは私にデリゲートの名前の代わりに最初の呼び出しを行ったメソッド名を与えているようです。

誰でもこの方法を知っていますか?

答えて

45

これは、デリゲートのアクションであるメソッドの名前を提供しています。それはちょうどラムダ式を使って実装されます。

あなたは現在の代理人を持っています。はBarkを呼び出しています。 Barkを直接使用する場合は、Barkメソッドの公開デリゲートを作成する必要がありますが、これはあまり簡単ではありません。実際にそれを呼びたいと思っています。あなたが必要としない場合は、使用することができ、それを呼び出すために、またはあなたはそれがとにかく最初の引数で呼び出されることをを知って

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); 
} 

あなた表現パラメータを作ることによって、このラウンドを取得することができツリーを代理人の代わりに使用しますが、ラムダ式が単なるメソッド呼び出しだった場合にのみ機能します。

+0

を述べただけのように、パラメータ表現の代わりにデリゲートすることによって、メソッド呼び出しの名前を取得することができます。私はそれを実行する必要はありませんでしたが、私はそれで何かをするクラスにメソッド名を渡さなければなりませんでした。文字列を取るのではなく、呼び出し元の型の安全性が私に本当の方法を与えなければならないことを望んでいました。いつものようにあなたは男です:) – Adam

+0

@Jonジェネリックメソッドで同じことをする方法はありますか? –

+0

@ArnabChakraborty:型引数も指定する必要がありますが、うまくいくと思います。今でも簡単にそれを試すことはできません。 –

5

あなたはジョンが美しく働い

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

それで 'Get (x => x.DoSomething(Arg1))'のように呼ばれるでしょうか?このメソッドを型セーフな方法でデリゲートとして渡したければ、このメソッドを呼び出さずに、 'Get (x => x.DoSomething)'のようにしたいのですが? – bflemi3

+0

はい。基本的に、C#5のC#6から 'nameof'演算子を実行する方法はありますか? –

関連する問題