2011-11-08 10 views
5

強く型付けされたメソッドの名前をラムダ式として引数や括弧を付けずに渡すことはできますか?私は次のような方法があればパラメータを指定せずに引数として強く型付けされたメソッドを使用する

たとえば、:

MyClassのは、MVC、たとえば、のために責任を負うことになる
return new MyClass<CalleeClass>(c => c.MethodA); //Note: no()'s or arguments 

public class CalleeClass 
{ 
    public void MethodA(obj param1, obj param2) 
    { 
     ... 
    } 
} 

を私は経由して他の場所でこのメソッドを呼び出すしたいと思いますメソッド名をターゲットとしてルーティングします。ここでの目標は、コントローラメソッドを使用して厳密に型指定されたビューを使用できるようにすることです。使用されない「ダム」パラメータを提供する必要はありません。

現在、メソッド名を使用するために次のようなコードを使用していますが、このスタイルでは依然として偽の引数や括弧を渡す必要があります。

public void MyClass<T>(Expression<Action<T>> action) 
{ 
    var methodName = (action.Body as MethodCallExpression).Method.Name; 
} 

EDIT:混乱のため申し訳ありませんが、私は最初だけで、私はあなたが必要と思ったものを含めることによって、問題を単純化しようとした、そしてそうすることで、いくつかの重要な情報を残しました。ここでの究極の目標は、MyClassにジェネリック型+ラムダ式を受け取り、ラムダ式が強く型付けされたメソッド名をオブジェクトのインスタンス化なしで渡すことができるようにすることです。 -MB

+0

オプションのパラメータを設定できませんか?また、それが括弧を持っていなければMethodCallExpressionは動作しません。私はかなり確信しています。 – chemicalNova

+0

パラメータはダムではありません。それらはコンパイラによって使用されています... –

+0

パラメータには害はありませんが、ルーティングのメソッド名だけが必要です。オブジェクトをインスタンス化しているという印象を与えるのは奇妙です。私はこれが可能であると確信していないので、私はここに来たのです。 :) –

答えて

2

は、あなたが実際にパラメータを指定せずにメソッドを渡すことができます。

class PassActionTest 
{ 
    public void Test() 
    { 
     var c = new C(); 
     var myClass = new MyClass(c.MethodA); 
    } 
} 

class MyClass 
{ 
    public MyClass(Action<object,object> action) 
    { 
     string methodName = action.Method.Name; 
    } 
} 

class C 
{ 
    public void MethodA(object param1, object param2) 
    { 
    } 
} 

EDIT:マット・ベックマンのEDITによると、MethodAを含むクラスをインスタンス化するべきではありません。私の新しいソリューションは、次のとおりです。

class PassActionTest 
{ 
    public void Test() 
    { 
     var myClass = new MyClass(c => c.MethodA); 
    } 
} 

class MyClass 
{ 
    public MyClass(Expression<Func<C, Action<object, object>>> expr) 
    { 
     UnaryExpression unaryExpr = (UnaryExpression)expr.Body; 
     MethodCallExpression methodCallExpr = (MethodCallExpression)unaryExpr.Operand; 
     ConstantExpression constantExpr = (ConstantExpression)methodCallExpr.Arguments[2]; 
     MethodInfo methodInfo = (MethodInfo)constantExpr.Value; 
     string methodName = methodInfo.Name; 
    } 

} 

class C 
{ 
    public void MethodA(object param1, object param2) 
    { 
    } 
} 

発現を分析する少し複雑ですが、私はそれをテストしてきたし、それが動作します。

+0

ここで問題を単純化しようとすると、次の行を追加するのを忘れたと思います。_return new MyClass (c => c.MethodA _)、クラスをインスタンス化したくないのでMethodAメソッド。上記の変更を参照してください。 –

+0

@MattBeckman:私の元の答えに編集を参照してください。 –

+1

[このコメント](http://stackoverflow.com/questions/8225302/get-the-name-of-a-method-using-an-expression#comment30751822_8228144)と[この回答](http:// stackoverflow .com/a/26976055/1270174)を使用してください。 –

0

あなたがでアクション<>デリゲートの存在を使用することができ、方法MethodA(の署名を照合デリゲートを宣言)と

public delegate void MethodADelegate(object param1, object param2); 

public MyClass(MethodADelegate methodParam) 
{ 
    //use the methodParam parameter 
} 

代わりのMyClassクラスのコンストラクタにパラメータとしてデリゲートを使用することができます.Netによって提案された@Olivier

1

メソッド名が必要な場合は、Delegate(http://msdn.microsoft.com/en-us/library/system.delegate.aspx)を使用することをお勧めします。 :

public MyClass(Delegate action) 
{ 
    var methodName = action.Method.Name; 
} 

これは、私はあなたがそれを渡すときにデリゲート型を指定する必要がありますだと思う除いて動作します。これは、リファクタリングがあまりにも、動作するよう強く型付けされたそれをすべてしておこう

{ 
    ... 
    return new MyClass((Action<object,object>)c.MethodA); 
}