简单的解决方案:从C的角度来看,lambda表达式是非类型化的(它的类型是
LambdaExpression
)在运行时,它是“正确的类型”(例如
Expression<Action<Program, T2>>
,这是可能的,因为
Expression<T>
子类
LambdaExpression语言
)
Expression<Action<Program, object>> e1 = (t, v) => t.Set(v);
var type = typeof(int);
var par1 = e1.Parameters[0];
var par2 = Expression.Parameter(type);
// if type is a value type, you have to expressly box it
Expression conv = type.IsValueType ? (Expression)Expression.Convert(par2, typeof(object)) : par2;
// We "chain" the two expressions
InvocationExpression invoke = Expression.Invoke(e1, par1, conv);
LambdaExpression lambda = Expression.Lambda(invoke, par1, par2);
var compiled = lambda.Compile();
// sanity check,
bool lambdaTypeIsExpected = typeof(Expression<>).MakeGenericType(typeof(Action<,>).MakeGenericType(typeof(Program), type)) == lambda.GetType();
请注意,如果您需要
LambdaExpression语言
对于某些ORM或其他子系统,并非所有库都支持
Invoke
(可以使用表达式重写器删除)或
Convert
(这是从值类型转换为引用类型所必需的)。我甚至看过不喜欢的图书馆
object
完全停止(我已经尝试过很多次了:-)