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

如何在protobuf-net中实现自定义ISerializer处理object类型序列化?

使用protobuf-net自定义序列化器处理含object成员的类型

核心实现思路

当类包含object类型成员时,通过[ProtoContract(Serializer = typeof(YourCustomSerializer))]指定自定义序列化器,序列化时写入目标对象的类型标识(如程序集限定名),反序列化时读取该标识还原对应类型实例,完全规避代理方案的额外内存开销。

自定义序列化器实现步骤

自定义序列化器需实现IProtoSerializer接口,核心实现Write和Read方法,同时通过Features属性声明序列化器特性。

示例代码

  1. 标记目标类
[ProtoContract(Serializer = typeof(ObjectHolderSerializer))]
public class ObjectHolder
{
    public object Content { get; set; }
}
  1. 实现自定义序列化器
public class ObjectHolderSerializer : IProtoSerializer
{
    // 返回当前序列化器处理的目标类型
    public Type ExpectedType => typeof(ObjectHolder);

    // 表示序列化器是否返回新实例(此处返回true,会创建新的ObjectHolder)
    public bool ReturnsValue => true;

    // 表示是否需要传入旧实例进行更新(此处不需要,直接创建新实例)
    public bool RequiresOldValue => false;

    // 声明序列化器特性,按需组合枚举值
    public SerializerFeatures Features => 
        SerializerFeatures.SupportsNull | SerializerFeatures.WireTypeString;

    public object Read(object existingValue, ProtoReader source)
    {
        // 1. 读取类型标识
        var typeFullName = source.ReadString();
        if (string.IsNullOrEmpty(typeFullName))
        {
            return new ObjectHolder { Content = null };
        }
        
        // 2. 解析类型并反序列化对象
        var targetType = Type.GetType(typeFullName);
        var content = Serializer.NonGeneric.Deserialize(targetType, source);
        
        return new ObjectHolder { Content = content };
    }

    public void Write(object value, ProtoWriter dest)
    {
        var holder = (ObjectHolder)value;
        if (holder.Content == null)
        {
            // 写入空标识表示null值
            ProtoWriter.WriteString(string.Empty, dest);
            return;
        }
        
        // 1. 写入类型的程序集限定名
        var typeFullName = holder.Content.GetType().AssemblyQualifiedName;
        ProtoWriter.WriteString(typeFullName, dest);
        
        // 2. 序列化实际对象内容
        Serializer.NonGeneric.Serialize(dest, holder.Content);
    }
}

SerializerFeatures 详解

SerializerFeatures是标志枚举,用于告知protobuf-net自定义序列化器的行为特性,常用值包括:

  • SerializerFeatures.SupportsNull:标识序列化器可处理null值,框架会跳过默认的null检查逻辑
  • SerializerFeatures.WireTypeString:表示序列化器输出字符串格式的wire数据,帮助框架正确处理编码解码
  • SerializerFeatures.FixedSize:若序列化后数据长度固定,可设置此标志优化性能
  • SerializerFeatures.CategoryMessage:标识该序列化器处理消息类型(类似普通ProtoContract标记的类),框架按消息规则处理
  • SerializerFeatures.IgnoreConstructor:允许序列化器绕过构造函数直接实例化对象,适用于无参数构造函数缺失的场景

注意事项

  • 类型标识建议使用AssemblyQualifiedName,确保跨程序集类型可正确解析;若担心名称过长,可自定义类型映射表(如用短字符串替代全名)减少序列化体积
  • 确保object成员对应的类型已正确配置protobuf-net特性(如[ProtoContract]、[ProtoMember]),否则无法正常序列化
  • 若需进一步优化内存分配,可在Read/Write方法中复用已有对象(需结合RequiresOldValue = true),或使用内存池化技术处理临时数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:17:49