具有运行时已知类型的表达式 Lambda
Expression Lambda with types known at runtime
我正在尝试创建一些表达式,其中我将使用 lambda 来创建两种方法:选择器和条件。简化用法为 condition(selector(data))
,但中间类型仅在运行时已知。我有以下代码,只要中间类型是对象,它就可以工作,但在运行时我知道真正的类型并想使用它。
public static ICondition<TData> GetRelayConditionByReflection(string name, string message, string assemblyName,
string fullyQualifiedName, string conditionMethodName, string selectorMethodName) {
var asm = Assembly.LoadFrom(assemblyName);
var type = asm.GetType(fullyQualifiedName);
var selectorMi = type.GetMethod(selectorMethodName, BindingFlags.Static | BindingFlags.Public);
var conditionMi = type.GetMethod(conditionMethodName, BindingFlags.Static | BindingFlags.Public);
var tCondType = selectorMi.ReturnType;
var returnType = typeof(RelayCondition<,>);
var typeArgs = new[] { typeof(TData), tCondType };
var paramTData = Expression.Parameter(typeof(TData), "data");
var selector = Expression.Lambda<Func<TData, object>>(
Expression.Call(selectorMi, paramTData), paramTData).Compile();
var paramTCondition = Expression.Parameter(tCondType, "condition");
var condition = Expression.Lambda<Func<object, bool>>(
Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile();
return (ICondition<TData>)Activator.CreateInstance(returnType.MakeGenericType(typeArgs), name, condition, message, selector);
}
具体来说,有Expression.Lambda<Func<TData, object>>
和Expression.Lambda<Func<object, bool>>
,其中object
目前只允许中间类型为object。
是否可以使用仅在运行时已知的类型来创建它?我对整个问题的其他方法持开放态度,只要性能不是 attrocius。
如果你不需要隐式向下转换(例如声明一个 Func<object>
而实际上你方法 return 一个 Func<Foo>
),你可以使用非泛型 Expression.Lambda()
方法。它 return 是 LambdaExpression
,但实际上它 return 是 Func<>
或 Action
的 Expression<>
向下转换为 LambdaExpression
(Expression<>
是 LambdaExpression
) 的子类,所以:
var condition = Expression.Lambda(
Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile();
现在 condition
是 Delegate
,但实际上它是 Func<>
(或者 Action
,如果它具有 return 类型 void
).
我正在尝试创建一些表达式,其中我将使用 lambda 来创建两种方法:选择器和条件。简化用法为 condition(selector(data))
,但中间类型仅在运行时已知。我有以下代码,只要中间类型是对象,它就可以工作,但在运行时我知道真正的类型并想使用它。
public static ICondition<TData> GetRelayConditionByReflection(string name, string message, string assemblyName,
string fullyQualifiedName, string conditionMethodName, string selectorMethodName) {
var asm = Assembly.LoadFrom(assemblyName);
var type = asm.GetType(fullyQualifiedName);
var selectorMi = type.GetMethod(selectorMethodName, BindingFlags.Static | BindingFlags.Public);
var conditionMi = type.GetMethod(conditionMethodName, BindingFlags.Static | BindingFlags.Public);
var tCondType = selectorMi.ReturnType;
var returnType = typeof(RelayCondition<,>);
var typeArgs = new[] { typeof(TData), tCondType };
var paramTData = Expression.Parameter(typeof(TData), "data");
var selector = Expression.Lambda<Func<TData, object>>(
Expression.Call(selectorMi, paramTData), paramTData).Compile();
var paramTCondition = Expression.Parameter(tCondType, "condition");
var condition = Expression.Lambda<Func<object, bool>>(
Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile();
return (ICondition<TData>)Activator.CreateInstance(returnType.MakeGenericType(typeArgs), name, condition, message, selector);
}
具体来说,有Expression.Lambda<Func<TData, object>>
和Expression.Lambda<Func<object, bool>>
,其中object
目前只允许中间类型为object。
是否可以使用仅在运行时已知的类型来创建它?我对整个问题的其他方法持开放态度,只要性能不是 attrocius。
如果你不需要隐式向下转换(例如声明一个 Func<object>
而实际上你方法 return 一个 Func<Foo>
),你可以使用非泛型 Expression.Lambda()
方法。它 return 是 LambdaExpression
,但实际上它 return 是 Func<>
或 Action
的 Expression<>
向下转换为 LambdaExpression
(Expression<>
是 LambdaExpression
) 的子类,所以:
var condition = Expression.Lambda(
Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile();
现在 condition
是 Delegate
,但实际上它是 Func<>
(或者 Action
,如果它具有 return 类型 void
).