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

Unity MLAPI网络事件系统运行时调用泛型反序列化方法问题

报错原因

你的反射方案出现转换错误核心是两个问题:

  1. 类型字符串获取错误:你用data.ToString()拿到的只是类的短名,若类存在命名空间、或者处于不同程序集,Type.GetType()会直接返回null,需要获取完整的限定类型名
  2. 转换逻辑错误:Convert.ChangeType仅支持基础类型(值类型、字符串等)的转换,不支持自定义引用类型的派生类转换,你反序列化得到的结果本身就是EventArgs的子类,直接强转即可,不需要调用转换方法

修复方案

方案1:修复你的反射实现

首先修改发送端的类型字符串获取逻辑:

// 原来的错误写法
string argsTyp = data.ToString();
// 替换为获取完整程序集限定名,保证跨命名空间/程序集也能正确找到类型
string argsTyp = data.GetType().AssemblyQualifiedName;

然后修改反序列化的反射代码:

Type argsType = Type.GetType(argsType);
if (argsType == null || !typeof(EventArgs).IsAssignableFrom(argsType))
{
    // 类型非法直接返回,避免后续报错
    return;
}
MethodInfo method = typeof(EventArgsSerializer).GetMethod(nameof(EventArgsSerializer.Deserialize));
MethodInfo genericMethod = method.MakeGenericMethod(argsType);
var result = genericMethod.Invoke(null, new object[]{data});
// 直接强转即可,不需要Convert.ChangeType
EventArgs eventArgs = (EventArgs)result;
triggeredEvent.Invoke(clientId, eventArgs);

方案2:更简洁的非反射实现(推荐)

Unity的JsonUtility本身提供了非泛型的反序列化重载,不需要通过反射调用泛型方法,性能更好也更稳定:
首先给你的EventArgsSerializer加一个非泛型重载:

public static class EventArgsSerializer
{
    public static string Serialize(EventArgs eventArgs)
    {
        return JsonUtility.ToJson(eventArgs);
    }

    public static T Deserialize<T>(string input)
    { 
        return JsonUtility.FromJson<T>(input);
    }

    // 新增非泛型重载
    public static EventArgs Deserialize(string input, Type targetType)
    {
        if (!typeof(EventArgs).IsAssignableFrom(targetType))
        {
            throw new ArgumentException("目标类型必须继承自EventArgs");
        }
        return (EventArgs)JsonUtility.FromJson(input, targetType);
    }
}

然后你可以直接删掉所有反射代码,反序列化一行搞定:

Type argsType = Type.GetType(argsType);
if (argsType == null) return;
EventArgs eventArgs = EventArgsSerializer.Deserialize(data, argsType);
triggeredEvent.Invoke(clientId, eventArgs);

注意事项
  • 所有自定义的EventArgs子类必须添加[Serializable]特性,否则JsonUtility无法正常序列化
  • 类中需要序列化的字段必须是公开的,或者添加[SerializeField]特性,JsonUtility不支持自动属性的序列化
  • 如果担心传输AssemblyQualifiedName字符串冗余、或者有安全风险,可以提前给所有EventArgs子类分配唯一的int ID,本地维护Dictionary<int, Type>的映射表,传输时仅传ID,比传字符串更省流量,也能避免恶意构造类型字符串带来的安全问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:15:04