You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行时类型未知时,如何编译Expression<Func<ObjType,TDest>>?

解决运行时动态类型Expression的编译问题

问题场景

你定义了如下方法:

public static TDest SimpleStuff<TDest>(object obj) where TDest : new()
{
     var objType = obj.GetType();
     var destinationType = typeof(TDest);
     var method = typeof(SimpleMapper).GetMethod("CreateInit", BindingFlags.Static | BindingFlags.Public, Type.EmptyTypes);
     var genericMethod = method.MakeGenericMethod(objType, destinationType);
     var expressionFuncAsObject = genericMethod.Invoke(typeof(SimpleMapper), null);
       
     // ... 后续代码
}

其中expressionFuncAsObject的实际类型为Expression<Func<ObjType, TDest>>,但由于ObjType和TDest的具体类型仅在运行时可知,无法直接强转为该类型以调用.Compile()方法。

你尝试用Expression.GetFuncType配合Expression.Lambda编译,代码如下:

var funcType = Expression.GetFuncType(objType , destinationType);
var func = Expression.Lambda(funcType,
                Expression.Parameter(destinationType), Expression.Parameter(objType ) 
                ).Compile();

但运行时抛出错误:

System.InvalidOperationException: 'variable '' of type 'B' referenced from scope '', but it is not defined'

解决方案

核心原因

你手动构造的ParameterExpression和原表达式expressionFuncAsObject中引用的参数并非同一实例,表达式树验证时会判定引用了未定义的变量,因此报错。正确的做法是直接利用已有表达式对象,通过反射调用其Compile方法。

实现代码

  1. 调用已有表达式的Compile方法
// 获取expressionFuncAsObject实例的Compile方法
var compileMethod = expressionFuncAsObject.GetType().GetMethod("Compile", Type.EmptyTypes);
// 执行Compile得到委托实例
var compiledFunc = compileMethod.Invoke(expressionFuncAsObject, null);
  1. 执行编译后的委托
    如果需要执行该委托并返回结果,可通过DynamicInvoke方法(所有委托都继承自Delegate类,自带该方法):
// 传入obj作为参数,执行委托
var result = compiledFunc.GetType().GetMethod("DynamicInvoke").Invoke(compiledFunc, new[] { obj });
// 强转为TDest类型返回
return (TDest)result;

补充说明

不需要重新构造Lambda表达式,因为原表达式expressionFuncAsObject已经是一个完整的Expression<Func<...>>实例,包含了正确的参数定义和逻辑,直接调用它自己的Compile方法即可完成编译。

内容的提问来源于stack exchange,提问作者Nachman Berkowitz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 11:02:40