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

泛型方法注册与动态调用中的类型转换问题求助

解决动态方法注册中的类型转换与序列化问题

看起来你已经搭好了方法注册的架子,但卡在了运行时动态处理类型转换和序列化这一步——毕竟泛型是编译时确定类型,而你需要根据注册时存在MethodData里的类型信息来处理byte[]和返回值。我来一步步帮你解决这个问题:

核心问题分析

你的ProcessIncomingRequest现在有几个关键问题:

  • 它是static方法,但list是NetworkServer的实例成员,根本访问不到
  • 泛型的Serializer<Tin>和Send<Tout>无法直接使用运行时获取的ArgumentType/ReturnType
  • 代码里有拼写错误:NULL应该是C#小写的null,it应该是method

解决方案步骤

1. 调整ProcessIncomingRequest为实例方法

首先把方法改成实例成员,这样才能访问到当前服务器实例的list:

public void ProcessIncomingRequest(NetworkClient cl, string name, byte[] data)
{
    var method = list.SingleOrDefault(x => x.Name.Equals(name));
    if(method == null) return; // 找不到方法直接返回
    // ...后续逻辑
}

2. 实现动态反序列化

你需要把泛型的Serializer<T>改成支持传入目标类型的版本,或者通过反射调用泛型序列化方法。比如先定义一个通用的反序列化方法:

// 假设你原来的泛型反序列化是这样的:
// public static Tin Serializer<Tin>(byte[] data) { ... }
// 我们通过反射来动态调用它:
private object Deserialize(byte[] data, Type targetType)
{
    // 获取泛型方法的定义
    var serializeMethod = typeof(YourSerializerClass).GetMethod("Serializer");
    // 构造具体类型的泛型方法
    var genericMethod = serializeMethod.MakeGenericMethod(targetType);
    // 调用并返回结果
    return genericMethod.Invoke(null, new object[] { data });
}

然后在Process里调用:

var finalData = Deserialize(data, method.ArgumentType);

3. 动态调用方法并处理返回值

调用MethodInfo.Invoke后,根据ReturnType是否为null来判断是Action还是Func:

var retn = method.MethodInfo.Invoke(null, new[] { cl, finalData });

// 如果是有返回值的方法(Func),则序列化并发送
if (retn != null && method.ReturnType != null)
{
    // 同样用反射调用泛型的Send方法
    SendResult(cl, retn, method.ReturnType);
}

4. 实现动态发送返回值

和反序列化同理,动态调用泛型的Send<T>方法:

private void SendResult(NetworkClient cl, object result, Type returnType)
{
    var sendMethod = typeof(NetworkClient).GetMethod("Send");
    var genericSend = sendMethod.MakeGenericMethod(returnType);
    genericSend.Invoke(cl, new[] { result });
}

修改后的完整代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

struct MethodData 
{ 
    public string Name; 
    public MethodInfo MethodInfo; 
    public Type ReturnType; 
    public Type ArgumentType; 
}

class NetworkServer 
{ 
    private List<MethodData> list = new List<MethodData>();

    public void RegisterMethod<In, Out>(string name, Func<NetworkClient, In, Out> method) 
    { 
        list.Add(new MethodData() 
        { 
            MethodInfo = method.Method, 
            Name = name, 
            ReturnType = typeof(Out), 
            ArgumentType = typeof(In) 
        }); 
    }

    public void RegisterMethod<In>(string name, Action<NetworkClient, In> method) 
    { 
        list.Add(new MethodData() 
        { 
            MethodInfo = method.Method, 
            Name = name, 
            ArgumentType = typeof(In), 
            ReturnType = null // 标记为无返回值
        }); 
    }

    public void ProcessIncomingRequest(NetworkClient cl, string name, byte[] data) 
    { 
        var method = list.SingleOrDefault(x => x.Name.Equals(name)); 
        if(method == null) return;

        // 动态反序列化参数
        var finalData = Deserialize(data, method.ArgumentType); 
        // 调用目标方法
        var retn = method.MethodInfo.Invoke(null, new[] { cl, finalData }); 

        // 处理返回值
        if(retn != null && method.ReturnType != null) 
        {
            SendResult(cl, retn, method.ReturnType);
        }
    }

    // 动态反序列化逻辑
    private object Deserialize(byte[] data, Type targetType)
    {
        // 替换成你实际的序列化类名
        var serializerType = typeof(YourSerializerUtility);
        var serializeMethod = serializerType.GetMethod("Serializer", BindingFlags.Public | BindingFlags.Static);
        if(serializeMethod == null)
            throw new InvalidOperationException("Serializer method not found");
        
        var genericMethod = serializeMethod.MakeGenericMethod(targetType);
        return genericMethod.Invoke(null, new object[] { data });
    }

    // 动态发送返回值逻辑
    private void SendResult(NetworkClient cl, object result, Type returnType)
    {
        var sendMethod = typeof(NetworkClient).GetMethod("Send", BindingFlags.Public | BindingFlags.Instance);
        if(sendMethod == null)
            throw new InvalidOperationException("Send method not found");
        
        var genericSend = sendMethod.MakeGenericMethod(returnType);
        genericSend.Invoke(cl, new[] { result });
    }

    public void Start()
    {
        // 你的启动逻辑
    }
}

// 假设的NetworkClient类
class NetworkClient
{
    public void Send<T>(T data)
    {
        // 发送逻辑
    }
}

// 假设的序列化工具类
static class YourSerializerUtility
{
    public static T Serializer<T>(byte[] data)
    {
        // 你的反序列化逻辑,比如用Newtonsoft.Json或Protobuf
        return default;
    }
}

class Program
{
    static void Main() 
    { 
        NetworkServer server = new NetworkServer(); 
        server.RegisterMethod<int, bool>("CheckValue", CheckValue); 
        server.RegisterMethod<string>("Log", NotifyLogger); 
        server.Start(); 
    }

    static bool CheckValue(NetworkClient cl, int value) 
    { 
        return value >= 10; 
    }

    static void NotifyLogger(NetworkClient cl, string logger) 
    { 
        Console.WriteLine($"Incoming Logger request : {logger}"); 
        // MyLogger.Write($"[SERVER] {logger}");
    }
}

额外提示

  • 如果你的序列化库本身支持直接序列化/反序列化为object(比如Newtonsoft.Json的Deserialize(byte[], Type)),可以直接用,不用反射调用泛型方法,效率会更高
  • 可以考虑缓存反射获取的MethodInfo,避免每次请求都反射,提升性能
  • 注意异常处理:比如找不到方法、反序列化失败、方法调用抛出异常等情况,要加try-catch块

内容的提问来源于stack exchange,提问作者Maurice S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:19:08