IDisposable継承クラスのDIコンテナ登録
IDisposable を継承したクラスを DIコンテナ に登録している状況で、取得したインスタンスの Dispose をどのように行うかで悩んでいます。
ここでは UnityContainer を前提に話を進めますが、他のDIライブラリでのソリューションがありましたら ご教示頂きたく思います。
自分の認識
自分の認識をまとめてみました。認識誤りがありましたらご教示ください。 これらの詳細は別途 Qiita の記事フィールドにまとめています。
DIコンテナのライフサイクルが PerContainer(Singleton) や Hierarchical (Scoped) の場合、DIコンテナが生成インスタンスの参照を保持している。
DIコンテナはそれ自体が Dispose されるときに、参照保持インスタンスを Dispose してくれる。DIコンテナのライフサイクルが Transient の場合、DIコンテナはインスタンスの生成後に関与しない。(参照を保持しないので Dispose もしてくれない)
なので、Transient で登録されたインスタンスが IDisposable を継承している場合、インスタンスを取得したユーザが Dispose する責任を負う。
本題の悩み
ここまでの認識を踏まえますと、以下になると思います。
DIコンテナ からインスタンスを取得したユーザは、取得インスタンスが DIコンテナ内 でどのようなライフサイクルで管理されているかを認識して管理しなければならない。
- IDisposable を継承している Transient 管理のインスタンスを取得した場合 は、自分で Dispose しなければならない。
- IDisposable を継承していても Singleton 管理のインスタンスは(他も参照してるので)Dispose してはならない。
これだと、ユーザはインスタンスの管理を DIコンテナ にお任せしているにも関わらず、DIコンテナ のインスタンス管理状況を知る必要があり、依存関係に違和感を感じます。
DIコンテナのユーザが、この程度の管理責任を被るのは 仕方ないものなのでしょうか?
UnityContainer での補足
他のDIライブラリのことが分からないので、UnityContainer に限定して補足いたします。
UnityContainer であれば、ユーザ側もDIコンテナから管理されている型のライフサイクル(参照の保持有無)を取得できますので、その結果に応じて ええ感じ に管理することも可能です。(手間ですが…)
UnityContainer には、Transient だけど参照保持するライフサイクル(PerContainerTransient)が用意されていますので、そちらを使うことでユーザの Dispose 責任を解消できます。
ですが、Transient が存在している以上、開発中に ライフサイクル が変更される可能性もありますので、そこまで考慮すると結局 ユーザ側で DIコンテナ の管理状況を調べて対応する しか無くなってします…
参考
以下に本悩みと同じ内容が挙がっていますが、回答は付いていません。
Disposing needed in Unity? - stackoverflow
When you register types that implement the IDisposable interface using the TransientLifetimeManager (you get a new instances each type you call Resolve on the container), it is up to you to call Dispose on the instance.
Transient の場合、Dispose を呼ぶのはユーザの責任です。
manually calling Dispose means you have to be sure that it's been registered with a TransientLifetimeManager
ユーザが手動で Dispose を呼ぶには、(取得インスタンスが)Transient で登録されていることを確認する必要がある。
終わりに
趣味プログラマ なので知り合いに詳しい方がおらず、的外れなことを質問しちゃっているかもしれません…