現在、密結合だらけでバグ修正等が大変なことになっているプログラムの全面的な再開発をしており、DIコンテナを活用して解決をしていこうとしています。
調べていくうちにDIコンテナの使い方で混乱してきたので、どなたかご教授願います。
コンテナに依存?
以下のようなシンプルなクラスを考えます。LogicAクラスはIServiceに依存していて、その実体はコンストラクタインジェクションするとします。
c#
1// 注入したいインターフェース 2public interface IService { void Call(); } 3// DIコンテナでインターフェースにマップされる具象 4public class ServiceA : IService { void Call() { /* 処理 */ } } 5// インターフェースを注入されるクラス 6public class LogicA { 7 private IService _service; 8 public LogicA(IService service) { _service = service; } 9 public void Call() { _service.Call(); } 10}
このLogicAクラスを利用する場合、LogicAのインスタンス生成時にIServiceの実体がないといけません。IServiceの実体の作り方はコンテナが知っています。つまり、
c#
1public class LogicAUser { 2 public void CallLogicA() { 3 // マップ済のコンテナから生成 4 // コンテナインスタンスは、グローバル変数のコンテナまたはコンストラクタで受領 5 var service = container.Resolve<IService>(); 6 var logic = new LogicA(service); 7 logic.Call(); 8 } 9}
とする必要があると思うのですが、結局LogicAUserクラスはコンテナに依存した作りになってしまいます。
質問事項
- これって「DIコンテナをサービスロケーター的に使う」というアンチパターンになってしまっているように見えるのですが、使い方は合っていますか?
- 個人的な理解としては、LogicAUserを含むアセンブリの参照をするアセンブリがコントロールできるなら問題ない(そもそもDIコンテナを使っている時点でそれに依存しているため)、そうでないならコンテナに依存してしまうんで問題がある、という認識ですが、合っていますか?
- 問題ない場合、コンテナへの参照はどのように利用クラスに引き渡すべきですか?極論をいえばDIコンテナで生成する処理がスレッドセーフであればどうでもいいですか?
- 生成部分をコンテナに依存しないようにするにはどのようにすべきですか?ILogicAFactoryインターフェースとLogicAFactoryクラスを作ってLogicAUserクラスにILogicAFactoryをコンストラクタインジェクションする方法が思いつきましたが、冗長になりすぎる気がします。
回答1件
あなたの回答
tips
プレビュー