.NET Coreの汎用ホストでMicrosoft.Extensions.DependencyInjection
を使ったDI ContainerにAssembly Scanしてサービスを自動登録する簡易的な仕組みを作ったのでその備忘録です。
目次
成果物
Gistに上げています。
DI Containerに登録したいSericeの実装
例えば以下のCQRSっぽいコードがあったとします。
Microsoft.Extensions.DependencyInjection
にはAssembly Scanをして自動的にDI Containerへ登録する機能がありません。(ないですよね?)
そのためQuery, Commandの数が多い場合、DI Containerへ登録するのが辛くなってしまいました。。
先日の記事ではAutoFac
やMediatR
あたりを使っていましたが、やっぱ余分なライブラリの使用は減らしたいよなー。高機能じゃなくていいからAssembly Scanして自動登録して欲しいなー。ということで思い付きで書いてみました。
基本的な仕組み
Assembly
でExportedTypes
を参照して、そいつがInterfaceなのかClassなのか、Classなら継承してるクラスは誰なのか、などを検索してInterface, Classを抽出してDIに登録する流れです。
登録関数は3つ作りました。
- 指定したAssembly内のInterface, Classを全て登録する関数
- 指定したInterfaceを継承しているClassのみを登録する関数
- 指定したGenericなInterfaceを継承したClassのみを登録する関数
以下がそのコードです。
指定したAssembly内のInterface, Classを全て登録する関数
指定したInterfaceを継承しているClassのみを登録する関数
指定したGenericなInterfaceを継承したClassのみを登録する関数
使い方
IHostBuilder
の作成時にConfigureService
内で各関数を呼ぶだけです。
Interfaceと実装Classが異なるAssemblyに格納されているケースを考慮し、Interface, Class毎のAssemblyを指定する必要があったりします。
問題点
DI Containerへの登録はAddTransient
固定で行っています。
Singleton
やScope
などの生存期間で登録する場合はそこら辺の制御機能を盛り込む必要があります。
Microsoft.Extensions.DependencyInjection
は後から登録したServiceが優先されるようなので、生存期間を変更したいものだけ後から個別にService追加することで回避することも可能です。
※ここがMicrosoft.Extensions.DependencyInjection
のいいところですね。
Dummy役Serviceなんかも楽に挿入できるわけです。
おわり
もともとCQRSのQuery, Commandに絞った用途で考えていたので、この程度で十分って感じですね。
Assembly舐めるので起動速度がちょっと遅くなるかとは思いますが、所詮趣味プロジェクトですしお寿司🍣
以上です。