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

如何传递参数数量可变的Func<T>委托

实现支持可变参数数量的Func委托调用方案

要实现无需重载且调用语法简洁的GetValue方法,核心思路是利用自定义委托包装类+隐式类型转换,让不同参数数量的Func可以自动适配到同一个方法参数中,同时保留编译时的类型检查。

具体实现步骤

  1. 定义一个包装类DynamicFunc,用于统一封装不同参数数量的委托,并提供统一的调用入口:
public class DynamicFunc
{
    private readonly Delegate _underlyingFunc;

    public DynamicFunc(Delegate func)
    {
        _underlyingFunc = func ?? throw new ArgumentNullException(nameof(func));
    }

    // 统一的调用方法,接收可变参数数组并转发给原委托
    public object Invoke(params object[] args)
    {
        // 可添加参数数量匹配校验,避免运行时错误
        var methodParams = _underlyingFunc.Method.GetParameters();
        if (args.Length != methodParams.Length)
        {
            throw new ArgumentException($"Expected {methodParams.Length} parameters, got {args.Length}");
        }
        return _underlyingFunc.DynamicInvoke(args);
    }

    // 为无参Func添加隐式转换
    public static implicit operator DynamicFunc(Func<object> func)
    {
        return new DynamicFunc(func);
    }

    // 为单参数Func添加隐式转换
    public static implicit operator DynamicFunc<TArg>(Func<TArg, object> func)
    {
        return new DynamicFunc(func);
    }

    // 为双参数Func添加隐式转换
    public static implicit operator DynamicFunc<TArg1, TArg2>(Func<TArg1, TArg2, object> func)
    {
        return new DynamicFunc(func);
    }
}
  1. 修改GetValue方法,让它接收DynamicFunc参数,内部通过包装类的Invoke方法调用原委托:
public object GetValue(string name, DynamicFunc func)
{
    // 替换成你实际获取参数的逻辑,比如从上下文/配置中根据name取参数
    object[] parameters = GetParametersByName(name);
    
    return func.Invoke(parameters);
}

// 示例:模拟根据名称获取参数的逻辑
private object[] GetParametersByName(string name)
{
    return name switch
    {
        "Bob" => Array.Empty<object>(),
        "Joe" => new object[] { 123 },
        "Henry" => new object[] { 456, "test" },
        _ => throw new ArgumentOutOfRangeException(nameof(name))
    };
}

调用方式(完全符合你的需求)

// 无参数
var result1 = GetValue("Bob", () => "Bob Smith");

// 1个参数
var result2 = GetValue("Joe", (i) => $"Joe {i.ToString()}");

// 2个参数
var result3 = GetValue("Henry", (i, e) => $"i: {i.ToString()}, e: {e.ToString()}");

未来扩展

如果后续需要支持3个及以上参数的委托,只需要在DynamicFunc类中添加对应的隐式转换方法即可,不需要修改GetValue的方法签名:

// 支持三参数Func
public static implicit operator DynamicFunc<TArg1, TArg2, TArg3>(Func<TArg1, TArg2, TArg3, object> func)
{
    return new DynamicFunc(func);
}

方案优势

  • 调用者无需任何显式类型转换,语法简洁自然
  • 无需重载GetValue方法,核心逻辑集中在包装类中
  • 保留了编译时的类型检查,避免纯dynamic方案的运行时风险
  • 扩展成本低,新增参数数量支持只需要添加对应转换方法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:08:04