我試圖創建一個擴展方法,該方法生成並存儲已編譯的Lambda表達式,並返回表單類型的泛型類型類的實例,其中Class和T只在運行時才知道(由用戶選擇驅動)。爲僅在運行時已知的類型創建編譯後的Expession.Lambda
由於我是表達式樹新手,我正在努力研究出正確的語法。下面
的「makeGenericExpression」給運行時出現以下錯誤
「的靜態方法需要空實例,非靜態方法需要 非空實例。」
但它是完全可能的,makeGenericLambda也有缺陷(我只是還沒有得到它尚未)
這裏是我到目前爲止所(我使用C#4.0)
public static class TypeXtensions
{
public static object GetGenericInstance<TArg>(this Type type, TArg argument)
{
return InstanceCreationFactory<TArg>
.CreateGenericInstanceOf(type, argument);
}
private static class InstanceCreationFactory<TArg>
{
private static readonly Dictionary<Type, Func<TArg, object>> GenericInstanceCreationMethods =
new Dictionary<Type, Func<TArg, object>>();
public static object CreateGenericInstanceOf(Type type, TArg arg)
{
CacheGenericInstanceCreationMethodIfRequired(type);
return GenericInstanceCreationMethods[type].Invoke(arg);
}
private static void CacheGenericInstanceCreationMethodIfRequired(Type type)
{
if (GenericInstanceCreationMethods.ContainsKey(type)) return;
var makeGenericMI = type.GetType().GetMethod("MakeGenericType");
var paramExpression = Expression.Parameter(typeof (TArg), "argument");
var makeGenericExpression = Expression.Call(makeGenericMI, paramExpression);
// Compile the Expression into a Func which takes the type argument and returns the constructed object:
var makeGenericLambda = Expression
.Lambda<Func<TArg, object>>(makeGenericExpression)
.Compile();
GenericInstanceCreationMethods[type] = makeGenericLambda;
}
}
}
爲了完整,呼叫我使用這樣的
private void InputDataChanged(object sender, InputConnector<IndicatorStrategy>.InputDataChangedEventArgs e)
{
var baseType = e.Payload.GetType().BaseType;
if (baseType == null) return;
var arg = baseType.GetGenericArguments()[0];
var test = typeof (ComplexIndicatorDataGenerator<>).GetGenericInstance(arg);
}
我很困惑,'arg'總是會成爲'Type',那麼爲什麼'TArg'是通用的? – svick
@svick因爲TArg可以是10個不同的類中的任何一個,這取決於用戶在運行時的選擇,並且擴展方法中的「this」可以是直到運行時再次未知的4種類型中的任何一種。在我的例子中,我試圖創建一個ComplexIndicatorDataGenerator。 –
這不是你的代碼所做的。 'TArg'總是會成爲'Type'。 – svick