2015-07-22 69 views
1

我有一個表達的getter這樣的:轉換通用吸氣表達反對吸氣式

var expression =() => SomeInstance.Nr; 

它傳遞給方法:

public void AddExpression<T>(Expression<Func<T>> func) 

現在我想轉換是通用的表達

Expression<Func<object>> 

我不是很肯定,如果我甚至可以做到這一點。我想是這樣的:

var converted = Expression.Convert(func, typeof(object)); 
var objectExpression = Expression.Lambda<Func<object>>(Expression.Call(converted.Method), func.Parameters); 

但是,當我打電話

var number = objectExpression.Compile()(); 

它不會返回屬性值。

的代碼可以在這裏進行測試: http://volatileread.com/utilitylibrary/snippetcompiler?id=25062

更新: 看來,調用上纏繞有第二次:

var converted = Expression.Convert(func, typeof(object)); 
var objectExpression = Expression.Lambda<Func<object>>(Expression.Call(converted.Method), func.Parameters); 
var anotherDelegate = objectExpression.Compile().Invoke(); // would have expected the value here 
var value = ((Delegate)anotherDelegate).DynamicInvoke(); // this now does return the value 

回答

3

不要使用委託Expression.Call - 這只是那裏調用方法。相反,您想使用Expression.Invoke,這是專門用於調用代表的。此外,關鍵在做表達式樹是包裝 - 調用內部的委託,轉換的結果,並在拉姆達把這個包:

Expression<Func<int>> inputExpression =() => 42; 

var newLambda = 
    Expression.Lambda<Func<object>> 
    (
     Expression.Convert 
     (
      Expression.Invoke(inputExpression), 
      typeof(object) 
     ) 
    ); 

Console.WriteLine(newLambda.Compile()()); // Prints 42. 

newLambdaExpression<Func<object>>並調用它給你42,如你期望。

當然,這使得將其作爲擴展方法變得相當容易(儘管如果需要它們,您可能希望使用模板生成所有不同的Func<...>重載)。

注意,這隻會如果任何LINQ提供你實際上使用工作支持Invoke - 在這種情況下,它不是一個問題,因爲拉姆達編譯器可以處理它,但如果你需要使用的東西像這樣與例如EntityFramework,你需要採取稍微不同的方法 - 你需要解開內部lambda,轉換內部lambda的身體,然後再包裹它在另一個lambda。對於一個無參數的表達,這是相當容易:

Expression<Func<int>> inputExpression =() => 42; 

var newLambda = 
    Expression.Lambda<Func<object>> 
    (
    Expression.Convert(inputExpression.Body, typeof(object)) 
); 

Console.WriteLine(newLambda.Compile()()); // Prints 42. 

而且,完整性,注意,這僅僅在進行內表達確實是一個常量表達式,而不是報價 - 但如果你需要引用嵌套表達式,你可能不會問這個問題:D

+0

我沒有'轉儲'可用這是在.net 4.5? (我在4.0上工作) – derape

+0

@derape這只是LINQPad輔助方法 - 它就像一個超級權力的'Console.WriteLine' :) – Luaan

+0

Thanks =)適合我! – derape