如何在Core包中序列化protobuf-net接口?无需修改Api包
Protobuf-net 无特性实现接口序列化方案
完全可以通过不使用特性的方式实现,核心是利用protobuf-net提供的RuntimeTypeModel进行运行时配置,无需修改Api包中的IBase接口,也不用在实现类上添加[ProtoInclude]或其他序列化特性。以下是具体实现参考方向:
1. 运行时注册接口与实现类的映射
在Core包的初始化逻辑中(比如启动时的配置方法),通过RuntimeTypeModel显式注册IBase接口及其所有需要序列化的实现类:
- 首先获取默认的模型实例(或创建自定义模型),为IBase接口添加子类型映射,每个子类型分配唯一的整数标签:
// 注册IBase接口及Core包内的实现类 var typeModel = RuntimeTypeModel.Default; var ibaseType = typeModel.Add(typeof(IBase), false); // 为Group分配标签1 ibaseType.AddSubType(1, typeof(Group)); // 为Base<int>分配标签2(若有其他泛型参数类型,如Base<string>,需单独注册) ibaseType.AddSubType(2, typeof(Base<int>)); - 同时注册包含ICollection
的Main类: typeModel.Add(typeof(Main), false);
2. 泛型实现Base的批量注册
如果Base
var ibaseType = RuntimeTypeModel.Default.Add(typeof(IBase), false); int nextTag = 3; // 延续之前的标签编号 // 扫描当前程序集及引用的程序集,找到所有Base<T>的实现 foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { foreach (var type in assembly.GetTypes()) { if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Base<>) && typeof(IBase).IsAssignableFrom(type)) { ibaseType.AddSubType(nextTag++, type); } } }
注意:标签编号需保证全局唯一,避免冲突。
3. 使用配置好的模型进行序列化/反序列化
不再使用protobuf-net默认的Serializer静态类,而是调用已配置的RuntimeTypeModel实例的方法:
// 序列化Main对象 using (var stream = new MemoryStream()) { RuntimeTypeModel.Default.Serialize(stream, mainInstance); byte[] serializedData = stream.ToArray(); } // 反序列化 using (var stream = new MemoryStream(serializedData)) { var deserializedMain = (Main)RuntimeTypeModel.Default.Deserialize(stream, null, typeof(Main)); }
额外注意事项
- 其他扩展包中新增的IBase实现类,只需在Core或主包能引用到该类型的地方,重复上述注册逻辑即可,无需修改Api包
- 若子类型分布在多个程序集,可在主包的初始化逻辑中统一扫描注册
- 标签编号建议提前规划,避免不同实现类使用相同标签导致序列化异常
内容的提问来源于stack exchange,提问作者glenn223
相关产品推荐
相关产品推荐

