DDDのValueObjectをCSVから一括生成する「UnitGeneratorTemplate」をリリースしました
私はValueObject好きなんですが、でも実装って案外面倒ですよね。
recordが登場してだいぶ楽になりましたが、それでも不十分な側面が多くあります。
それらの課題を解決してくれるライブラリーとしてUnitGeneratorがあります。
非常によくできていて痒い所に手が届くのですが、それで大量に作ると大変です・・・
というわけで、CSVに設定を定義すると一括生成してくれるテンプレートライブラリー「UnitGeneratorTemplate」をリリースしました!
UnitGenerator
UnitGeneratorTemplateはCSVに設定を記載することで、UnitGeneratorを利用したValue Objectを一括で自動生成するためのテンプレートパッケージです。
T4テンプレートとCSVを利用して、任意のUnitを一括で作成できます。
Getting Started
UnitGeneratorとUnitGeneratorTemplateをNuGetからインストールします。
- NuGet:UnitGenerator
- NuGet:UnitGeneratorTemplate
Install-Package UnitGenerator
Install-Package UnitGeneratorTemplate
パッケージをインストールすると、2つのファイルが追加されます。
- UnitGenerator.csv
- UnitGenerator.tt
UnitGenerator.csvに生成したいUnitを定義し、UnitGenerator.ttでコードを生成します。
こちらはCSVをVisual Studio Codeの「Edit csv」拡張で開いたものです。
CSVにはつぎのように指定します。
列 | 説明 | 指定例 |
---|---|---|
Name | 生成する構造体の名称 | UnitId |
Type | 値の型 | int |
Description | 生成する構造体のTypeコメント | UnitのIDを表す値オブジェクト |
Format | ToString時のフォーマット | {0:###,###,###} |
ImplicitOperator以降 | UnitGeneratorに指定する属性 | 指定しない場合は空。指定する場合はそれ以外。 |
CSVを編集したあと、UnitGenerator.ttファイルを開いて「Ctrl+s」を押すか、UnitGenerator.ttのコンテキストメニューから「カスタムツールの実行」を押します。
すると次のようにUnitGenerator.ttの下にUnitGenerator.csファイルが作成されます。
Validate
Validateの利用方法は、ほかのOptionとはやや異なります。
Validateを使う場合、判定ルールをつぎのいずれかの方法で指定します。
- CSVのValidate列に判定条件を記載する
- Validateメソッドをpartialに独自実装する
CSVのValidate列に判定条件を記載する
たとえばint型のUnitの場合に、値を10未満とする場合、Validate列に次のように記載します。
Name | Type | … | Validate | … |
---|---|---|---|---|
UserId | int | value < 10 |
この時、例外クラスとメッセージを変更したい場合、UnitGenerator.ttファイルを編集します。
<#@ template debug="false" hostspecific="true" language="C#" #>
...
<#
var validateException = "InvalidOperationException";
var validateExceptionMessage = "Invalid value range: {value}";
#>
validateExceptionとvalidateExceptionMessageを任意の値に変更してください。
Validateメソッドをpartialに独自実装する
この場合、CSVにはつぎのように有効化のみ指定します。
Name | Type | … | Validate | … |
---|---|---|---|---|
UserId | int | ✔ |
1文字以上、5文字以下の文字列であれば何を指定してもかまいません。
6文字以上の場合は、式が指定されているとして判断します。
Validateメソッドは、つぎのようにpartialとして実装してください。
public partial struct UserId
{
private partial void Validate()
{
if (5 < value) throw new InvalidOperationException($"Invalid value range: {value}");
}
}
Discussion