使用Protobuf-net在多个命名空间之间进行序列化
本文关键字:之间 序列化 命名空间 Protobuf-net 使用 | 更新日期: 2023-09-27 18:21:59
我一直在使用protobuf-net(2.0.0.480版本)对消息进行序列化。该应用程序使用CQRS方法,其中命令和事件被分离到不同的名称空间[和程序集]中。
代码将在运行时为从MessageBase继承的任何类动态添加类型。这是使用以下代码完成的:
// Used as a unique reference for each type in a member
private static int _sequence = 1000;
public static void RegisterAll()
{
RegisterAllDerivedFrom<MessageBase>();
}
public static void RegisterAllDerivedFrom<T>(params Assembly[] assemblies)
{
if (assemblies == null || assemblies.Length == 0)
{
assemblies = AppDomain.CurrentDomain.GetAssemblies();
}
var type = typeof(T);
var model = RuntimeTypeModel.Default;
var metaModel = model.Add(type, true);
RegisterAllBaseTypes(type, metaModel, model, assemblies);
}
private static void RegisterAllBaseTypes(Type type, MetaType metaModel, RuntimeTypeModel model, params Assembly[] assemblies)
{
foreach (var t in assemblies.SelectMany(a => a.GetTypes().Where(t => t.BaseType != null && t.BaseType == type)))
{
var subModel = model.Add(t, true);
metaModel.AddSubType(_sequence, t);
_sequence++;
RegisterAllBaseTypes(t, subModel, model, assemblies);
}
}
一些类型也被手动添加到默认运行时类型模型中:
RuntimeTypeModel.Default.Add(typeof(ReferenceNumber), true)
.AddSubType(100, typeof(Product))
.AddSubType(110, typeof(ProductGroup));
当所有消息都在中时,以上所有内容似乎都能正常工作
LogicalGrouping.Events
该项目向前推进,并添加了一个新的名称空间:
引用分组.命令
一旦添加ReferenceGrouping.Commands并尝试发送消息,就会抛出ProtoException。我为这种行为找到的唯一解决方法是将ReferenceGrouping.Commands中的Commands添加到LogicalGrouping.Events.
这是预期的行为吗?还是RuntimeTypeModel应该能够支持从完全不同的命名空间添加类?
查看代码,我强烈怀疑问题在于您没有可靠的(可重复的)子类型标识符。如果有,在序列化时:
- Foo
- SubFoo1(键=2)
- SubFoo2(键=5)
然后,在为反序列化配置模型时,至关重要的是,要有兼容的密钥;例如,您可以反序列化为:
- 酒吧
- MegaBar(键=2)
- UltraBar(键=5)
我的猜测是,添加子类型的机制并不能确保数字匹配。它需要一些线索。事实上,看着你的代码,我想知道它是否也会在当前崩溃,如果:
- 添加类型
- 删除类型
- 重命名类型
- 重新定位类型
- 只是。。。任何时候(不保证类型的顺序,IIRC)
我的建议是:在某个地方保留一个外部注册,以了解每个密钥在子类型方面的含义。或者:使用ProtoIncludeAttribute在代码中执行同样的操作。