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

运行时判断protobuf-net能否序列化/反序列化List等泛型类型的方案咨询

基于存储的类型名称判断protobuf-net可序列化的实现方案

实现思路

  • 第一步:将数据库存储的程序集限定名称转换为Type实例
  • 第二步:递归判断类型是否满足protobuf-net序列化要求,补全原生方法缺少的泛型容器参数校验逻辑

代码实现

using ProtoBuf;
using System;
using System.Collections.Concurrent;
using System.Linq;

public static class ProtobufSerializationChecker
{
    // 缓存校验结果,避免重复计算损耗性能
    private static readonly ConcurrentDictionary<Type, bool> _checkCache = new ConcurrentDictionary<Type, bool>();

    /// <summary>
    /// 根据存储的类型全限定名判断是否可被protobuf-net反序列化
    /// </summary>
    public static bool CanDeserialize(string typeAssemblyQualifiedName)
    {
        try
        {
            var targetType = Type.GetType(typeAssemblyQualifiedName, throwOnError: false);
            if (targetType == null)
                return false;

            return IsProtobufSerializable(targetType);
        }
        catch
        {
            return false;
        }
    }

    private static bool IsProtobufSerializable(Type type)
    {
        if (_checkCache.TryGetValue(type, out var result))
            return result;

        try
        {
            // 数组类型校验元素类型
            if (type.IsArray)
            {
                var elementType = type.GetElementType();
                result = elementType != null && IsProtobufSerializable(elementType);
                _checkCache.TryAdd(type, result);
                return result;
            }

            // 泛型类型先校验容器本身,再递归校验所有泛型参数
            if (type.IsGenericType)
            {
                if (!Serializer.NonGeneric.CanSerialize(type))
                {
                    result = false;
                    _checkCache.TryAdd(type, result);
                    return result;
                }

                var genericArguments = type.GetGenericArguments();
                result = genericArguments.All(IsProtobufSerializable);
                _checkCache.TryAdd(type, result);
                return result;
            }

            // 普通类型直接调用原生方法校验
            result = Serializer.NonGeneric.CanSerialize(type);
            _checkCache.TryAdd(type, result);
            return result;
        }
        catch
        {
            result = false;
            _checkCache.TryAdd(type, result);
            return result;
        }
    }
}

注意事项

  • 原生Serializer.NonGeneric.CanSerialize方法已经内置了自定义类型的ProtoContract特性校验、属性依赖类型的合法性校验,无需额外重复实现
  • 若运行环境未默认加载对应类型的程序集,可在程序启动时注册AppDomain.CurrentDomain.AssemblyResolve事件实现自定义程序集加载逻辑,避免类型加载失败
  • 所有异常分支都做了静默处理返回不可序列化,可根据业务需要调整为抛出指定异常或增加日志记录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:45:04