2010-05-31 95 views
4

我希望我錯過了一些明顯的東西,但我有一些麻煩定義一個方法,該方法需要方法的參數來獲取傳遞方法的方法信息。我不想實際執行該方法。NET Lambda傳遞方法參數

我希望能夠做到:

busObject.SetResolverMethod<ISomeInterface>(x=>x.GetNameById); 

凡GetNameById是在接口ISomeInterface定義的方法。在這種情況下,該方法的一個例子是傳遞的簽名是:

MyVarA GetNameById(int id){ .... } 

在上面的例子中,SetResolverMethod的身體應該能夠返回/存儲字符串‘GetNameById’。

沒有標準簽名被傳入的方法符合(除了它總是會返回某種類型的對象)。

目前我設置方法爲一個字符串(即「GetNameById」),但我希望它被編譯時檢查,因此這個問題。

+0

如果沒有標準的簽名,那麼你怎能稱呼呢?除非你強制作弊,否則會有一個標準的簽名(這將是可怕的)。 – colithium 2010-05-31 02:23:56

+0

如果傳入的方法沒有標準簽名,那麼您希望在編譯時檢查什麼? – 2010-05-31 02:23:58

+0

@colithium - 我從來沒有說過我想打電話給它。它是我需要的方法名稱。即我基本上想要MethodInfo。 – Rosstified 2010-05-31 02:28:38

回答

2

它不是特別漂亮/流利,但如果你真的想避免傳遞虛擬參數值,那麼你可以使用返回委託的表達式。

SetResolverMethod<ISomeInterface>(x => new Func<int, MyVarA>(x.GetNameById)); 

SetResolverMethod實施將是這個樣子:

public void SetResolverMethod<T>(Expression<Func<T, Delegate>> expr) 
{ 
    var unary = (UnaryExpression) expr.Body; 
    var methodCall = (MethodCallExpression) unary.Operand; 
    var constant = (ConstantExpression) methodCall.Arguments[2]; 
    var method = (MethodInfo) constant.Value; 
    Console.WriteLine(method.Name); 
} 

編輯:如果你願意創建作爲一套重載每個Func<>委託的,你可以通過包括提高流暢度方法參數類型在您的方法的通用參數類型中。

p.SetResolverMethod<ISomeInterface, int, MyVarA>(x => x.GetNameById); 

如您所見,調用者不再需要指定委託類型,從而節省大約8個字符。

我實現了三個重載爲0,1和2個參數:

public void SetResolverMethod<T, TResult>(Expression<Func<T, Func<TResult>>> expr) 
{ 
    SetResolverMethod((LambdaExpression) expr); 
} 

public void SetResolverMethod<T, T1, TResult>(Expression<Func<T, Func<T1, TResult>>> expr) 
{ 
    SetResolverMethod((LambdaExpression) expr); 
} 

public void SetResolverMethod<T, T1, T2, TResult>(Expression<Func<T, Func<T1, T2, TResult>>> expr) 
{ 
    SetResolverMethod((LambdaExpression) expr); 
} 

private void SetResolverMethod(LambdaExpression expr) 
{ 
    var unary = (UnaryExpression) expr.Body; 
    var methodCall = (MethodCallExpression) unary.Operand; 
    var constant = (ConstantExpression) methodCall.Arguments[2]; 
    var method = (MethodInfo) constant.Value; 
    Console.WriteLine(method.Name); 
} 
2

沒有辦法只傳遞方法本身。你可以通過將該方法包裝到委託中來完成,但爲此,必須要麼有SetResolverMethod方法來定義該委託的類型(這是你不能做的,因爲如你所說,沒有一個簽名) ,或者在調用時明確指定該類型,這會很髒。

你可以做的反而是有SetResolverMethod採取一個lambda表達式,需要ISomeInterface並返回任何,並與任何參數作爲表達式的主體通過該方法的實際執行。像這樣:

void SetResolverMethod<T>(Expression<Func<T,object>> expr); 

    ... 

    SetResolverMethod<ISomeInterface>(x => x.GetNameById(0)) 

SetResolverMethod方法不會實際執行的表情,只分析它 - 因此,你的方法實際上不會被執行。

這是你所需要的?

+0

是的,這是我可以提出的最好的。正試圖避免必須填充虛擬參數。乾杯。 – Rosstified 2010-05-31 02:41:39

+1

那麼,正如我所說 - 你不能真正傳遞一個方法的引用,而沒有明確地指定它的簽名(甚至更多 - 委託類型)的地方。此外,想一想:重載會發生什麼?你如何區分它們而不指定參數?所以虛擬參數幾乎是你唯一的方法。 – 2010-05-31 03:09:04