しばらくの間、CQRS/DDD の原則とパターンを調査しており、ストレージ モデルを WriteModel と ReadModel に分割したサンプル プロジェクトの実装を開始しました。WriteModel は単純な NoSQL に似たデータベースを使用します。このデータベースでは、集計がキーと値のスタイルで格納され、値は集計の単なるシリアル化されたバージョンです。
現在、ドメイン モデルの集約をストレージ内外でシリアライズおよびデシリアライズするために ProtoBuf-Net を検討しています。この投稿以外に、この分野で ProtoBuf-Net を使用するためのガイダンスやヒントは見つかりませんでした。要点は、集約のシリアライゼーションとデシリアライゼーションの (理想的な) 要件は、ドメイン モデルがこのインフラストラクチャの問題について可能な限り知識を持たないようにすることです。これは、次のことを意味します。
- クラスに属性はありません
- シリアル化のためだけに、コンストラクター、ゲッター、セッター、またはその他のコードはありません。
- 可能な任意の (カスタム) タイプを使用し、シリアル化/逆シリアル化する機能。
これまでのところ、完全に正常に機能する集計の最初のバージョンのシリアル化のみを実装しました。-instance を使用してRuntimeTypeModel.Default
、実行時に 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 でどのように処理しますか?
2 番目の質問は、ポイント 3 に関するものです。追加の構成作業を行う場合、ProtoBuf-Net は任意の型を処理できますか? -typeを使用するときに発生する例外について読んだことがありますDateTimeOffset
。これにより、すべての型をすぐに使用できるフレームワークでシリアル化できるわけではないと思いますが、これらの型を RuntimeTypeModel に登録することでシリアル化できますか? 私もそこに行きたいですか?それとも、単純なもの以外の一般的な .NET 型をシリアル化することを忘れた方がよいでしょうか?