gpt4 book ai didi

c# - 使用 Protobuf-net 跨多个命名空间序列化

转载 作者:行者123 更新时间:2023-11-30 16:26:12 25 4
gpt4 key购买 nike

我一直在开发一个使用 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);
}
}

一些类型也被手动添加到 Default RuntimeTypeModel 中:

RuntimeTypeModel.Default.Add(typeof(ReferenceNumber), true)
.AddSubType(100, typeof(Product))
.AddSubType(110, typeof(ProductGroup));

当所有消息都在:

LogicalGrouping.Events

项目向前推进并添加了一个新的命名空间:

ReferenceGrouping.Commands

添加 ReferenceGrouping.Commands 并尝试发送消息后,将抛出 ProtoException。我发现的针对此行为的唯一解决方法是将 ReferenceGrouping.Commands 中的命令添加到 LogicalGrouping.Events 中。

这是预期的行为还是 RuntimeTypeModel 应该能够支持从完全不同的命名空间添加的类?

最佳答案

根据我的评论,Protobuf-net 根本不关心 namespace 、类型名称或成员名称,因为它使用数字键作为标识符(根据 protobuf 规范)。这意味着您可以在不同的程序集中对完全不同的模型进行反序列化,只要数字有意义即可。

查看代码,我强烈怀疑问题在于您没有可靠(可重复)的子类型标识符。如果有,在序列化时:

    • SubFoo1 (key=2)
    • SubFoo2(键=5)

然后,在配置反序列化模型时,兼容的 key 非常重要;例如你可以反序列化为:

  • 酒吧
    • MegaBar(键=2)
    • super 栏(键=5)

我的猜测是您添加子类型的机制不能确保数字匹配。它需要一些线索。实际上,查看您的代码,我想知道如果出现以下情况,它目前是否也会中断:

  • 添加类型
  • 删除类型
  • 重命名类型
  • 重定位类型
  • 只是...任何时候(不保证类型的顺序,IIRC)

我的建议是:在某个地方保留每个键在子类型方面的含义的外部注册。或者:使用 ProtoIncludeAttribute 在代码中执行相同的操作。

关于c# - 使用 Protobuf-net 跨多个命名空间序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9068163/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com