🐥note.

小鳥とMicrosoft <3 なエンジニアの技術Blog📚

Assembly Scanして自動的にMicrosoft.Extensions.DependencyInjectionのDI ContainerにService登録する仕組み

.NET Coreの汎用ホストでMicrosoft.Extensions.DependencyInjectionを使ったDI ContainerにAssembly Scanしてサービスを自動登録する簡易的な仕組みを作ったのでその備忘録です。

目次

成果物

Gistに上げています。

DI Containerに登録したいSericeの実装

例えば以下のCQRSっぽいコードがあったとします。

f:id:piyo_esq:20191226223612p:plain
CQRSっぽいコード

Microsoft.Extensions.DependencyInjectionにはAssembly Scanをして自動的にDI Containerへ登録する機能がありません。(ないですよね?)
そのためQuery, Commandの数が多い場合、DI Containerへ登録するのが辛くなってしまいました。。

先日の記事ではAutoFacMediatRあたりを使っていましたが、やっぱ余分なライブラリの使用は減らしたいよなー。高機能じゃなくていいからAssembly Scanして自動登録して欲しいなー。ということで思い付きで書いてみました。

基本的な仕組み

AssemblyExportedTypesを参照して、そいつがInterfaceなのかClassなのか、Classなら継承してるクラスは誰なのか、などを検索してInterface, Classを抽出してDIに登録する流れです。

登録関数は3つ作りました。

  • 指定したAssembly内のInterface, Classを全て登録する関数
  • 指定したInterfaceを継承しているClassのみを登録する関数
  • 指定したGenericなInterfaceを継承したClassのみを登録する関数

以下がそのコードです。

指定したAssembly内のInterface, Classを全て登録する関数

f:id:piyo_esq:20191226225057p:plain
指定したAssembly内のInterface, Classを全て登録する関数

指定したInterfaceを継承しているClassのみを登録する関数

f:id:piyo_esq:20191226224033p:plain
指定したInterfaceを継承しているClassのみを登録する関数

指定したGenericなInterfaceを継承したClassのみを登録する関数

f:id:piyo_esq:20191226221519p:plain
指定したGenericなInterfaceを継承したClassのみを登録する関数

使い方

IHostBuilderの作成時にConfigureService内で各関数を呼ぶだけです。
Interfaceと実装Classが異なるAssemblyに格納されているケースを考慮し、Interface, Class毎のAssemblyを指定する必要があったりします。

f:id:piyo_esq:20191226221604p:plain
使い方

問題点

DI Containerへの登録はAddTransient固定で行っています。 SingletonScopeなどの生存期間で登録する場合はそこら辺の制御機能を盛り込む必要があります。

Microsoft.Extensions.DependencyInjectionは後から登録したServiceが優先されるようなので、生存期間を変更したいものだけ後から個別にService追加することで回避することも可能です。
※ここがMicrosoft.Extensions.DependencyInjectionのいいところですね。 Dummy役Serviceなんかも楽に挿入できるわけです。

おわり

もともとCQRSのQuery, Commandに絞った用途で考えていたので、この程度で十分って感じですね。
Assembly舐めるので起動速度がちょっと遅くなるかとは思いますが、所詮趣味プロジェクトですしお寿司🍣

以上です。