我正在尝试制作一些表达式,我将使用lambda创建两个方法:选择器和条件.简化用法是条件(选择器(数据)),但中间类型仅在运行时已知.我有以下代码,只要中间类型是对象,但在运行时我知道真正的类型,并希望使用它.
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.
是否可以使用仅在运行时知道的类型创建它?只要性能不是空间,我就会对整个问题的其他方法持开放态度.
最佳答案 如果您不需要隐式向下转换(例如,声明Func< object>实际上您返回Func< Foo>),则可以使用非通用的Expression.Lambda()方法.它返回一个LambdaExpression,但实际上它返回一个Expression<> Func<>或者动作下载到LambdaExpression(Expression<>是LambdaExpression的子类),所以:
var condition = Expression.Lambda(
Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile();
现在条件是一个委托,但实际上它是一个Func<> (如果返回类型为void,则为Action).