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

如何将多参数Func<T1,T2...,TResult>转为Func<object[],object>且无反射调用

核心问题

能否将不同参数数量的Func<T1, T2, ..., TResult>委托转换为统一的Func<object[], object>签名(参数合并为对象数组),且无需反射/动态调用即可直接执行?

示例预期实现方向:

public static void Register<T, TArg1, TArg2>(Expression<Func<TArg1, TArg2, T>> action)
{
    // 使用表达式方法转换函数... 
    Expression<Func<object[], object>> exp = Expression.Lambda<Func<object[], object>>(action.Body, action.Parameters);
    
    // 编译代码以备调用...
}

背景

正在构建一款用于发送、接收并处理RPC的P2P游戏库,RPC方法需注册到控制器类,收到匹配RPC时需传入参数调用方法。希望避免使用反射,因为注册时方法均为强类型,预期通过泛型、Lambda及表达式树实现目标。

当前实现及不足

目前的方案需将参数封装为对象,而非使用常规的逗号分隔参数形式,具体代码如下:

public abstract class GameActionBase
{
    public Func<object, object> Action { get; protected set; }
    public Type ArgsType { get; protected set; }
    public Type ReturnType { get; protected set; }
}

public class GameAction<TArgs, TReturn> : GameActionBase
{
    public GameAction(Func<TArgs, TReturn> gameAction)
    {
        ArgsType = typeof(TArgs);
        ReturnType = typeof(TReturn);
        Action = args => gameAction((TArgs)args);
    }
}

public static class GameActions
{
    private static Dictionary<string, GameActionBase> registered;

    static GameActions()
    {
        registered = new Dictionary<string, GameActionBase>();
        SubscribeActionEvents();
    }

    public static void Register(string actionName, GameActionBase actionInfo)
    {
        registered.Add(actionName, actionInfo);
    }

    public static void Unregister(string actionName)
    {
        registered.Remove(actionName);
    }

    private static void SubscribeActionEvents()
    {
        Events.ActionReceivedEvent += (sender, action) =>
        {
            ProcessActionReceived(action);
        };
    }

    private static void ProcessActionReceived(ActionEventArgs action)
    {
        GameActionBase info;
        if (registered.TryGetValue(action.Name, out info))
        {
            object args = JsonUtility.FromJson(action.Args, info.ArgsType);
            object res = info.Action(args);
            // etc...
        }
    }
}

示例RPC方法

public class TestActionClass
{
    public TestActionReceivedState TestActionReceived(TestActionReceivedArgs args)
    {   
        // 处理游戏操作

        // 返回结果
        return new TestActionReceivedState
        {
            state1 = args.firstArg,
            state2 = args.secondArg
        };        
    }
}

[System.Serializable]
public class TestActionReceivedState
{
    public string state1;
    public string state2;
}

[System.Serializable]
public class TestActionReceivedArgs
{
    public string firstArg;
    public string secondArg;
    public string thirdArg;
    public string fourthArg;
    public string fifthArg;
}

注册方法示例

TestActionClass testClass = new TestActionClass();
var testAction = new GameAction<TestActionReceivedArgs, TestActionReceivedState>(testClass.TestActionReceived);

GameActions.Register("TestActionReceived", testAction);

需求

希望创建泛型Register方法,接收表达式并将其转换为可存储在集合中的统一签名,实现无反射直接调用,同时支持任意参数组合以简化API。如何实现?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 18:53:13