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

如何将Expression<Action<T, object>>转换为Expression<Action<T, U>>?

实现运行时强类型表达式树构建

要解决这个问题,核心是利用表达式树API动态构建强类型委托,同时完成强类型参数到object的隐式转换,适配Set方法的参数要求。下面是具体的实现步骤和完整代码:

核心思路

我们需要手动拼接表达式树的各个节点:

  • 定义表达式的两个输入参数:Program实例,以及指定运行时类型的参数
  • 将强类型参数转换为object类型(适配Set方法的参数要求,值类型会自动完成装箱)
  • 构建调用Set方法的表达式节点
  • 最后把这些节点组合成强类型的Expression<Action<Program, T>>(其中T是SomeRuntimeType()返回的类型)

完整代码实现

using System;
using System.Linq.Expressions;
using System.Diagnostics;

class Program {
    private static Type SomeRuntimeType() => typeof(int);
    public void Set(object v) {
        Debug.WriteLine($"Setting value: {v}");
    }

    static void Main(string[] args) {
        Expression<Action<Program, object>> e1 = (t, v) => t.Set(v);
        var targetType = SomeRuntimeType();

        // 1. 获取Set方法的元信息
        var setMethod = typeof(Program).GetMethod(nameof(Set), new[] { typeof(object) });

        // 2. 定义表达式的两个输入参数
        var programParam = Expression.Parameter(typeof(Program), "t");
        var valueParam = Expression.Parameter(targetType, "v");

        // 3. 将强类型参数转换为object(自动处理值类型装箱)
        var convertedValue = Expression.Convert(valueParam, typeof(object));

        // 4. 构建调用Set方法的表达式节点
        var callExpr = Expression.Call(programParam, setMethod, convertedValue);

        // 5. 动态创建强类型的Expression<Action<Program, T>>
        var lambdaGenericType = typeof(Expression<>).MakeGenericType(
            typeof(Action<,>).MakeGenericType(typeof(Program), targetType)
        );
        var e2 = (LambdaExpression)Activator.CreateInstance(
            lambdaGenericType,
            callExpr,
            new[] { programParam, valueParam }
        );

        // 测试:编译并执行表达式
        var action = (Delegate)e2.Compile();
        action.DynamicInvoke(new Program(), 123);
    }
}

关键细节说明

  • 获取方法元信息:通过反射拿到Set方法的MethodInfo,这是构建方法调用表达式的基础
  • 参数定义:用Expression.Parameter定义表达式的输入参数,第二个参数是参数的名称(可自定义)
  • 类型转换处理:Expression.Convert会自动处理值类型的装箱操作,引用类型则直接完成类型转换,完美适配Set方法的object参数
  • 动态强类型表达式:因为targetType是运行时确定的,所以需要通过MakeGenericType动态创建Expression<Action<Program, T>>的类型,再用反射完成实例化

这样构建出来的e2就是你需要的强类型表达式,编译后可以直接传入对应类型的参数调用Set方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:23:03