
121. 生成された C# プロジェクトの中身
はじめに
コードジェネレータの障害対応が終わり、私の脳内モヤモヤを吐き出したので、概念モデルから変換による実装で生成された C# プロジェクトの中身を解説します。
生成された C# プロジェクト
健診受診のモデルは規模がほどほどに大きいので、障害対応で作成したテストモデルから生成された C# プロジェクトを使って説明します。同じ変換ルールに従うなら、どんな概念モデルでもパターンは一緒なので。

全体像を図に示しました。コードを生成すると言っても、実行するために必要なすべてのコードを生成するということではなく、共通部分はライブラリ化されていて、そのライブラリに合致した、可変部分のみを生成しています。共通ライブラリは NuGet パッケージ化されていて、www.nuget.org から自動的にダウンロードされて利用されます。
Kae.DomainModel.Csharp.Framework
Kae.DomainModel.Csharp.Framwork.Adaptor
外部から、変換された C# プロジェクトのライブラリを使用するための Adaptor の共通コード
Kae.DomainModel.Csharp.Framework.AdaptorExternalStorage.AzureDigitalTwins
Kae.DomainModel.Csharp.Framework.ExternalEntity
External Entity の実装 ー Timer や乱数、文字列等のよく使われるものを実装
プロジェクトフォルダー直下にある、DomainClass で始まる C# ファイルは、概念情報モデル上の概念クラスの名前を XXX とすると、
DomainClassXXXBase.cs
特徴値の実装
DomainClassXXXBaseOperations.cs
オペレーションの実装
モデル上でアクション記述がある場合は、それから生成された C# コードが存在
無い場合は、手書き実装をするためのスペースが存在
DomanClassXXXStateMachine.cs
状態モデルの状態名、イベント、遷移が宣言されている
DomainClassXXXStateMachineActions.cs
状態のエントリアクションから生成されたコード
というパターンです。また、
DomainClassDefs.cs
全ての概念クラスごとに interface を宣言
SubClassDefs.cs
is-a の Relationship を C# コードでたどりやすいようにする Utility ライブラリ
というファイルも生成されています。手書き実装なら、ひとつの概念クラスにつき、一つのファイルで interface を宣言するというような感じになるのでしょうが、自動生成なので一つにまとめています。
他に、概念ドメインに対して、以下のファイル群が生成されます。DDD は概念ドメインの名前に置き換わります。
CIMDDDLib.cs
生成されたコード群全体の初期化などを実装
メソッドやメンバ変数がそれっぽいのが見て取れますね。
CIMDDDLibOperations.cs
概念ドメインの Domain Functions の実装
InstanceRepositoryInMemory.cs
メモリ上で概念インスタンスのデータを保持するための仕組みの実装
※ Note で斜体文字が使えればいいのに…
更に、Adaptor というフォルダーがあり、そこには、
DDDAdaptor.cs
外部から生成コードを使用するための実装
DDDAzureDigitalTwinsAdaptor.cs
Azure Digtal Twins と接続するための可変コードの実装
という二つのファイルが生成されています。前者は、

のような構成になっています。概念ドメイン全体から生成されたコードをビルドして出来上がった DLL ライブラリをインポートして、設定の供給、インスタンスの作成、初期化、Domain Function、イベント送信の Invocation Specification の取得と、それらの起動を行うためのメソッド群が実装されています。これらは、いかなる概念ドメインから生成されたライブラリコードでも、必ずあるので、外部コードは、C# の Reflection 機構を使って、必要な method の参照の取得が可能になっています。
一般的な通常のプログラミングしか経験のない人達にはちょっと奇妙に見えるかもしれませんが、Domain Function にしろイベント送信にしろ、
method の名前
method の戻り値のデータ型
method の引数
引数のデータ型
がわかりさえすれば、コード上で直接 method の名前を書くようなスタイルでなくても、生成されたライブラリに実装された method はいくらでもコールできるよということ。
…う~む…これを書いていて、C# の Attribute 機構を使っても同じようなことができるなぁ…と思い至り、記事のネタとしよう!
話を戻して…
例えば、Domain Function は、GetDomainOperationSpec というメソッドをコールすると、どんな名前でどんな引数を持つ Function があるかすべての情報が取得できるようになっていて、InvokeDomainOperation というメソッドを、その範囲にある名前や引数で指定してあげると、Domain Function の実装コードが実行されるという仕組み。イベントもそうだし、概念クラスを指定した概念インスタンスの取り出しも全て同じパターンで実装されています。
…う~む… Domain Function なのにその変換結果がDomainOperation というのは奇妙ですね…これも宿題ということで。
このあたり、詳しい話は、概念モデルから Adaptor を生成してシステムに組み込む|Knowledge & Experience に書いてあるので、もっと深く知りたい人は、そちらを読んでみてくださいまし。
最後に
今回は、これでおしまい。
次回は、生成されたコードを実際に実行する方法を紹介します。
ここから先は
Azure の最新機能で IoT を改めてやってみる
2022年3月にマイクロソフトの中の人から外の人になった Embedded D. George が、現時点で持っている知識に加えて、頻繁に…
この記事が気に入ったらチップで応援してみませんか?