2010-08-24 105 views
1

給出下面的變量之一,如何'檢查'它們以獲取傳入的參數值?即12345在lambda /表達式樹內尋找

System.Func<DateTime> f1 =() => DateTime.Now.AddDays(12345); 

System.Linq.Expressions.Expression<System.Func<DateTime>> 
         f2 =() => DateTime.Now.AddDays(12345); 

編輯:

下面的兩個答案通過的Mikael和柯克都回答我的問題,一部開拓創新。 但是,現在我已經使這個更復雜一點來處理「現實生活」了。 理想我正在尋找一個「一般」的解決方案,這將有一些工作alongs的下面幾行:

var days = 123; 
var hours = 456; 
System.Func<DateTime> f1 =() => DateTime.Now.AddDays(days).AddHours(hours); 
Expression<System.Func<DateTime>> f2 =() => DateTime.Now.AddDays(days).AddHours(hours); 

我真正追求的是產生unikey辦法「鑰匙」給予了lamda表達。 我的想法是使用方法名稱和參數名稱/值對,但我歡迎其他建議!謝謝。

+0

'f1'確實包含的信息,但只有通過檢查從C#編譯器生成的IL。如果執行了'f2',則在運行時編譯並且C#編譯器只創建一個表達式樹,您可以使用'Expression'類型和子類型來檢查。 – Richard 2010-08-24 15:40:53

回答

2

如果您的意思是值12345,則該數據僅在f2中可用。對於F2:

MethodCallExpression call = (MethodCallExpression)f2.Body; 
ConstantExpression arg = (ConstantExpression)call.Arguments[0]; 
Console.WriteLine(arg.Value); 
1

我可以看到從F1獲得它的唯一方法是:

int days = (f1() - DateTime.Now).Days; 

我懷疑是你想要的。

但是,如果函數的主體與您的示例一樣清晰地定義,那麼從f2獲取值是可能的,而且並不困難。它會開始像((f2 as LambdaExpression).Body as MethodCallExpression)....

我可能需要很長時間才能找出確切的過程,但它可能會更容易,因爲您只需在調試器中檢查f2即可。

3

作爲除了柯克沃爾的答案,如果你想擁有12345作爲一個對象,你可以使用以下命令:

public void Run() 
    { 
     System.Linq.Expressions.Expression<System.Func<DateTime>> f2 =() => DateTime.Now.AddDays(12345); 

     MethodCallExpression call = (MethodCallExpression)f2.Body; 
     ConstantExpression arg = (ConstantExpression)call.Arguments[0]; 

     var value = GetValue(arg); 
     Debug.WriteLine(value); 
    } 

    private object GetValue(ConstantExpression expression) 
    { 
     Expression conversion = Expression.Convert(expression, typeof(object)); 
     var getterLambda = Expression.Lambda<Func<object>>(conversion); 

     var getter = getterLambda.Compile(); 

     return getter(); 
    }