2011-11-08 13 views
5

Czy można przekazać silnie wpisaną nazwę metody jako wyrażenie lambda bez podania parametrów i/lub nawiasów?Używanie mocno wpisanej metody jako argumentu bez określania parametrów

Na przykład, jeśli mam następujące metody:

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

chciałbym wywołać tę metodę gdzie indziej poprzez:

return new MyClass<CalleeClass>(c => c.MethodA); //Note: no()'s or arguments 

Gdzie MojaKlasa byłby odpowiedzialny za, powiedzmy, MVC routing przy użyciu nazwy metody jako celu. Chodzi o to, że chcemy mieć możliwość używania silnie typowanych widoków za pomocą metod kontrolera, a nie chcę podawać "głupich" parametrów, które nie są używane.

Obecnie używam kodu podobnego do poniższego w celu użycia nazw metod, ale ten styl nadal wymaga podania fałszywych argumentów i/lub nawiasów.

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

EDIT: Przepraszamy za zamieszanie, ale początkowo starał się uprościć tę kwestię jedynie w tym, co pomyślałem, że trzeba, iw ten sposób pominięte pewne kluczowe informacje. Ostatecznym celem jest to, aby MyClass otrzymywał ogólne wyrażenie typu + lambda, a wyrażenie lambda może przekazywać silnie wpisaną nazwę metody bez tworzenia instancji obiektu. -MB

+0

Nie można ustawić parametrów opcjonalnych? Ponadto: MethodCallExpression nie będzie działać, jeśli nie mam nawiasu, jestem prawie pewien. – chemicalNova

+0

Parametry nie są głupie; są używane przez kompilator ... –

+0

Bez uszczerbku dla parametrów, ale potrzebujemy tylko nazwy metody dla routingu i wydaje się dziwne, aby sprawiać wrażenie, że tworzymy obiekt.Nie jestem przekonany, że jest to możliwe, dlatego przyjechałem tutaj. :) –

Odpowiedz

2

Rzeczywiście można przekazać metodę bez parametrów:

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: Według EDIT Matt Beckman, klasa zawierająca sposób A nie powinno być instancja. Moje nowe rozwiązanie to:

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

Analiza wypowiedzi jest nieco skomplikowana, ale przetestowałem ją i działa.

+0

Próbując uprościć problem tutaj, myślę, że zapomniałem dodać, że ta linia powinna brzmieć: _zwróć nową MyClass (c => c.MethodA) _, ponieważ nie chcę tworzyć instancji klasy, która ma metoda MethodA. Zobacz zmiany powyżej. –

+0

@MattBeckman: Zobacz edycję do mojej oryginalnej odpowiedzi. –

+1

Zobacz [ten komentarz] (http://stackoverflow.com/questions/8225302/get-the-name-of-a-method-using-an-expression#comment30751822_8228144) i [ta odpowiedź] (http: // stackoverflow .com/a/26976055/1270174) do użycia w środowisku wykonawczym v4.5. –

0

Można zadeklarować delegata dopasowanie podpis metody sposób A() i użyć delegata jako parametr do konstruktora klasy MojaKlasa

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

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

Alternatywnie, można użyć działaniem <> delegata obecny w .Net zgodnie z sugestią @Olivier

1

Jeśli potrzebujesz tylko nazwy metody, polecam użycie Delegate (http://msdn.microsoft.com/en-us/library/system.delegate.aspx) :

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

Działa to z wyjątkiem myślę, że trzeba określić typ delegata podczas przechodzenia go:

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

To będzie trzymać to wszystko silnie wpisany w taki sposób, refaktoryzacji zadziała też.

Powiązane problemy