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

如何通过表达式创建支持可变参数构造函数的Func<Type,object[],object>?

用Expression实现支持可变参数构造的实例创建器

要实现你需要的Creator方法,核心是为每个目标Type预编译适配其构造函数的委托并缓存——直接每次调用都生成表达式会抵消性能优势,缓存是关键。下面是具体实现:

核心实现代码

using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Linq.Expressions;

public static class InstanceCreator
{
    // 线程安全的缓存:存储Type到对应构造委托的映射
    private static readonly ConcurrentDictionary<Type, Func<object[], object>> _constructorCache = new();

    public static object Creator(Type targetType, object[] parameters)
    {
        // 从缓存获取委托,不存在则动态创建并缓存
        var constructor = _constructorCache.GetOrAdd(targetType, type =>
        {
            // 优先匹配参数实际类型的构造函数,适配重载场景
            var ctor = type.GetConstructor(parameters.Select(p => p.GetType()).ToArray()) 
                       //  fallback:尝试匹配object类型参数的构造函数(应对隐式转换)
                       ?? type.GetConstructor(parameters.Select(_ => typeof(object)).ToArray())
                       ?? throw new InvalidOperationException($"找不到匹配的构造函数:{type.FullName}");

            // 定义委托的输入参数:object[]类型的参数数组
            var paramExpr = Expression.Parameter(typeof(object[]), "args");

            // 构造每个构造参数的表达式:从数组取元素并转换为目标类型
            var argExprs = ctor.GetParameters()
                .Select((param, index) => 
                    Expression.Convert(
                        Expression.ArrayIndex(paramExpr, Expression.Constant(index)), 
                        param.ParameterType));

            // 生成调用构造函数的表达式
            var newExpr = Expression.New(ctor, argExprs);

            // 编译为可直接调用的委托
            return Expression.Lambda<Func<object[], object>>(newExpr, paramExpr).Compile();
        });

        return constructor(parameters);
    }
}

关键细节说明

  • 缓存机制:用ConcurrentDictionary保证多线程下的安全,避免重复编译同一个Type的构造逻辑,最大化性能优势。
  • 构造函数匹配:先尝试匹配参数实际类型的构造函数,适配重载场景;如果找不到,再尝试匹配参数为object类型的构造函数,覆盖隐式转换的情况。
  • 参数类型转换:通过Expression.Convert自动处理object数组元素到构造参数类型的转换,解决类型不匹配问题。

使用示例

// 测试类定义
public class ClassA
{
    public ClassA(int a, int b)
    {
        Console.WriteLine($"ClassA实例化:a={a}, b={b}");
    }
}

public class ClassB
{
    public ClassB(string text)
    {
        Console.WriteLine($"ClassB实例化:text={text}");
    }
}

// 调用方式完全符合需求
var a = InstanceCreator.Creator(typeof(ClassA), new object[] { 1, 2 });
var b = InstanceCreator.Creator(typeof(ClassB), new object[] { "some text" });

性能表现

编译后的委托性能接近直接new Class()的原生调用,远优于Activator.CreateInstance,且缓存机制避免了重复编译的开销,适合高频调用场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:47:31