DI(Dependency Injection)って何?
この言葉を聞いてもイメージが湧きにくいとおもいますが、日本語では依存性の注入と訳され、なおさら???となります。
依存というのは、例えば、あるクラスAの中で他のクラスBのインスタンスを使うように書かれているとき、クラスAはクラスBに依存(必要と)している、といいます。
依存というのは、使うとか必要としている、という感じでいい気がします。
下の例を考えてみます。 クラスAではクラスBにのインスタンスを使います。
using System; namespace DISample { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); var a = new A(); } } class A { public A() { var b = new B(); Console.WriteLine(b.CalcAdd(1, 2)); } } class B { public int CalcAdd(int x, int y) { return (x + y); } } }
じゃあクラスBのインスタンスをクラスAの外で作ってクラスAに渡してやればいいじゃない、ということで以下のようにします。
using System; namespace DISample { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); //クラスAの外でインスタンスを作って var b = new B(); //クラスAに渡してやる。 var a = new A(b); } } class A { public A(B b) { Console.WriteLine(b.CalcAdd(1, 2)); } } class B { public int CalcAdd(int x, int y) { return (x + y); } } }
この時点でクラスAの中からクラスBのインスタンスを作る部分がなくなりました。
しかし、クラスAは引数としてクラスBのインスタンスを受け取るようになっているので、これではまだクラスBが完成していないとクラスAを使えません。
まだクラスBが必要な作りになっています。
クラスBが完成していなくても、クラスBの代わりとなるものをクラスAに渡すにはどうしたらいいかというと、インターフェース(interface)を使います。
クラスAの引数の型をインターフェースにすると、そのインターフェースを実装しているクラスならなんでも渡せます。
クラスBが完成していなくても、とりあえずの結果を返す仮のクラスBもどきを渡してやることができます。
using System; namespace DISample { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); //クラスAの外でインスタンスを作って var b = new BModoki(); //クラスAに渡してやる。 var a = new A(b); } } class A { public A(IBclass b) { Console.WriteLine(b.CalcAdd(1, 2)); } } interface IBclass { int CalcAdd(int x, int y); } class B : IBclass { public int CalcAdd(int x, int y) { //開発中 return (x + y); } } class BModoki : IBclass { public int CalcAdd(int x, int y) { return 4; } } }
これでクラスAはクラスBを必要としなくなりました。 クラスAのテストができるようになります。
なるほど、あるクラスの中で使う他のクラスのインスタンスは全部外でインスタンス化して、引数として渡してやればいいんだな!
とそこで思うのが、「じゃあ10種類のインスタンスを使っていたら10個の引数を渡すの?100個だったら?」 という疑問。
それを解決するのが「DIコンテナ」?