介紹動態創建對象使用反射,鏈式方法和lambda表達式
我的應用程序使用方法鏈接因此被生成,並且被配置如下所示實例化的對象:
var car = new Car("Ferrari").Doors(2).OtherProperties(x = x.Color("Red"));
問題
我有一個requiremen t在運行時動態生成此對象 - 配置所需的鏈接方法將在運行時確定,因此所有內容都必須動態組合。我在過去使用反射來創建簡單的對象,如new Car("Ferrari", 2, "Red")
- 我很酷 - 但從來沒有任何鏈式方法包含lambda表達式作爲參數 - 這兩個因素真的讓我卡住了。我看着表達式樹和認爲,這是解決創建動態表達參數的一部分,但我完全卡住,試圖找出如何一起縫合與反射創建基礎對象和附加鏈接的方法。
感謝和讚賞
提前抽出時間來看看我的問題,你可能能夠提供任何指導或信息。
UPDATE:結論
非常感謝dasblinkenlight和喬恩斯基特了他們的答案。我選擇了dasblinkenlight的答案,因爲他的代碼示例讓我立即運行。對於方法鏈接我基本上使用相同的循環做法,接受的答案,所以我不會重複代碼,但下面是我寫的,動態轉換表達式樹的方法調用成可隨後通過反射Invoke()
執行動作代表的代碼所概述在dasblinkenlight的答案。正如喬恩指出的那樣,這真是問題的關鍵。
輔助類來存儲方法的元數據。
public struct Argument
{
public string TypeName;
public object Value;
}
public class ExpressionTreeMethodCall
{
public string MethodName { get; set; }
public IList<Argument> Arguments { get; set; }
public ExpressionTreeMethodCall()
{
Arguments = new List<Argument>();
}
}
組裝lambda表達式方法調用,然後返回它作爲在別處執行的動作委託(作爲參數在我的情況下傳遞給Invoke()
)的靜態方法。
public static Action<T> ConvertExpressionTreeMethodToDelegate<T>(ExpressionTreeMethodCall methodData)
{
ParameterExpression type = Expression.Parameter(typeof(T));
var arguments = new List<ConstantExpression>();
var argumentTypes = new List<Type>();
foreach (var a in methodData.Arguments)
{
arguments.Add(Expression.Constant(a.Value));
argumentTypes.Add(Type.GetType(a.TypeName));
}
// Creating an expression for the method call and specifying its parameter.
MethodCallExpression methodCall = Expression.Call(type, typeof(T).GetMethod(methodData.MethodName, argumentTypes.ToArray()), arguments);
return Expression.Lambda<Action<T>>(methodCall, new[] { type }).Compile();
}
非常感謝DAS ..所以用你提供的代碼 - 可以在「makeRed」行動對象中的「調用()」在通話過程中存儲在「chainedArgs」和執行鏈接循環? – mmacneil007
@ mmacneil007絕對,這就是主意。 'Action'是一個委託,它可以被存儲在'chainedArgs'數組中的一個數組中,並被傳遞給它相應的方法(在你的情況下,它就是'OtherProperties')。 –
dasblinkenlight
非常好,我相信這讓我走上了正確的道路。仍然圍繞表情樹包裹我的頭,但我認爲你在這裏概述的方法應該能夠做到。再次感謝! – mmacneil007