【发布时间】:2013-12-22 14:16:38
【问题描述】:
我正在尝试创建一个扩展方法,该方法生成和存储编译的 Lambda 表达式,并返回一个实例,其类型为泛型类型 T 的类,其中类和 T 仅在运行时已知(由用户驱动选择)。
由于我是表达式树的新手,我正在努力找出正确的语法。
下面的“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 因为 TArg 可以是 10 个不同的类中的任何一个,具体取决于用户在运行时的选择,并且扩展方法中的“this”可以是 4 种类型中的任何一种,直到运行时才知道。在我的示例中,我试图创建一个 ComplexIndicatorDataGenerator
. -
这不是您的代码所做的。
TArg永远是Type。 -
@svick 你说得对。您有什么建议可以让我实现使用(尝试的)表达式树方法生成 MyClass
实例的意图吗?
标签: c#-4.0 generics lambda expression-trees