2

我一直在探索 CQRS/DDD 原则和模式一段时间,并开始实施一个示例项目,在该项目中我将存储模型拆分为 WriteModel 和 ReadModel。WriteModel 将使用一个简单的类似 NoSQL 的数据库,其中聚合以键值样式存储,值只是聚合的序列化版本。

我现在正在使用 ProtoBuf-Net 对我的域模型聚合进出存储进行序列化和反序列化。除了这篇文章,我还没有找到在这个领域使用 ProtoBuf-Net 的任何指导或技巧。关键是聚合的序列化和反序列化的(理想)要求是域模型应该尽可能少地了解这个基础设施问题,这意味着以下内容:

  1. 类上没有属性
  2. 没有构造函数、getter、setter 或任何其他代码,只是为了序列化。
  3. 能够使用任何(自定义)类型并对其进行序列化/反序列化。

到目前为止,我只实现了我的聚合的第一个版本的序列化,它工作得非常好。我使用RuntimeTypeModel.Default-instance 在运行时配置 MetaModel 并且UseConstructor = false无处不在,这使我能够将序列化机制与我的域程序集完全分离。我什至实现了一个自定义的后反序列化机制,使我能够在 ProtoBuf-Net 将字段反序列化为有效实例后及时初始化字段。所以假设我有这样的 AggregateA 类:

[Version(1)]
public sealed class AggregateA
{
    private readonly int _x;
    private readonly string _y;

    ...
}

然后在我的序列化库中,我编写了以下代码:

var metaType = RuntimeTypeModel.Default.Add(typeof(AggregateA), false);
metaType.UseConstructor = false;
metaType.AddField(1, "_x");
metaType.AddField(2, "_y");
...

然而,我意识到到目前为止我只实现了基本场景,我现在开始考虑如何处理我的模型的版本控制。我对更大的重构场景特别感兴趣,其中类型 A 已拆分为类型 A1 和 A2,例如:

[Version(2)]
public sealed class AggregateA1
{
    private readonly int _x;

    ...
}

[Version(2)]
public sealed class AggregateA2
{
    private readonly string _y;

    ...
}

假设我有一堆 AggregateA 的序列化实例,但现在我的域模型只知道 AggregateA1 和 AggregateA2,你将如何使用 ProtoBuf-Net 处理这种情况?

第二个问题涉及第 3 点:如果您愿意投入一些额外的配置工作,ProtoBuf-Net 是否能够处理任意类型?我已经阅读了使用DateTimeOffset-type 时引发的异常,这让我认为并非所有类型都可以由框架开箱即用地序列化,但我可以通过在 RuntimeTypeModel 中注册这些类型来序列化它们吗?我应该那里吗?还是最好忘记序列化除简单类型之外的常见 .NET 类型?

4

1 回答 1

1

protobuf-net旨在使用可预测的已知模型。的确,一切都可以在运行时进行配置,但我没有考虑如何处理您的A1/A2场景,正是因为这不是一个受支持的场景(在我的辩护中,我看不出它与大多数序列化器)。想了想,如果你在某处有配置/映射数据,那么你可以简单地反序列化两次;即只要我们仍然告诉它AggregateA1._x映射到1AggregateA2._y映射到2,你可以这样做:

object a1 = model.Deserialize(source, null, typeof(AggregateA1));
source.Position = 0; // rewind
object a2 = model.Deserialize(source, null, typeof(AggregateA2));

然而,更复杂的调整需要额外的思考。

重新“任意类型”...定义“任意”;p 特别是,支持“代理”类型,这对某些转换很有用 - 但如果没有非常具体的“问题陈述”,很难完全回答。

概括:

protobuf-net 有一个预期的用途,包括序列化感知(属性等)和非感知场景(运行时配置等)——但它也适用于一系列更定制的场景(让你放弃原始阅读器/writer API,如果你愿意)。它不能也不能保证直接适合每个可以想象的序列化场景,它的表现如何取决于你离那个场景有多远。

于 2013-05-22T13:45:38.117 回答