I am trying to make some Expressions where I will be using a lambda to create two methods: a selector and condition. Simplified the usage is condition(selector(data))
, but the intemediate type is only known at runtime. I have the following code which works as long as the intemediate type is object, but at runtime I know the real type and would like to use that.
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);
}
Specifically, there is Expression.Lambda<Func<TData, object>>
and Expression.Lambda<Func<object, bool>>
where object
currently only allows the intemediate type to be object.
Is it possible to create this with a type known only at runtime? I am open for other approaches for the entire problem, as long as performance isn't attrocius.
答案 0 :(得分:2)
If you don't need implicit downcasting (for example declaring a Func<object>
when in truth you method returns a Func<Foo>
), you can use the non-generic Expression.Lambda()
method. It returns a LambdaExpression
, but in truth it returns a Expression<>
of Func<>
or of Action
downcasted to LambdaExpression
(Expression<>
is a subclass of LambdaExpression
), so:
var condition = Expression.Lambda(
Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile();
now condition
is a Delegate
, but in truth it is a Func<>
(or an Action
if it had a return type void
).