泛型方法注册与动态调用中的类型转换问题求助
解决动态方法注册中的类型转换与序列化问题
看起来你已经搭好了方法注册的架子,但卡在了运行时动态处理类型转换和序列化这一步——毕竟泛型是编译时确定类型,而你需要根据注册时存在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.
相关产品推荐
相关产品推荐

