DI / IoCのトピックは非常にシンプルですが、それがどのように機能し、なぜWebでそれが必要なのかを説明するのは非常に困難です。 これがUnityを使用した私の試みです。 トピックが十分に説明されているかどうかは、判断するのはあなた次第です。
簡単な例を作成しましょう:
// . -
public class MyService<br/>
{<br/>
public MyService()<br/>
{<br/>
⋮<br/>
}<br/>
public void DoSomething()<br/>
{<br/>
⋮<br/>
}<br/>
}<br/>
<br/>
// . -
public class MyWindow : Form<br/>
{<br/>
private MyService service;<br/>
public MyWindow()<br/>
{<br/>
service = new MyService();<br/>
}<br/>
}<br/>
<br/>
//
public class MyProgram<br/>
{<br/>
static void Main()<br/>
{<br/>
⋮<br/>
///
Application.Run( new MyWindow);<br/>
}<br/>
}<br/>
このコードには1つの問題があります
MyService
クラスは
MyService
クラスにあまりにも結びついています。 これは悪いので
MyService
から分離してMyWindow
単体テストを書くことはできません。 実際、統合テストが行われます。OtherService
しない限り、 OtherService
をOtherService
に置き換えることはできません。 複数のクラスがMyService
に依存している場合、それらすべてを変更する必要があります。- サービスで設定が必要な場合、それを使用する各クラスで設定する必要があります。
つまり、問題は
operator new()
です。 依存関係を適切に制御し、単独でオブジェクトをテストできるようにするには、この演算子を拒否する必要があります。
どうやって? これがまさにIoCおよびDIパターンの機能です。
IoC(制御の反転)は、オブジェクトの制御(この場合はオブジェクトの有効期間)がコンポーネントに割り当てられるパターンです。 何らかのアウトソーシング-オブジェクトを自分で作成する代わりに(
new()
)、いわゆるオブジェクトにリクエストします。 IoCコンテナー、つまり、有能なオブジェクトを生成できる工場。
確かに、コンテナからオブジェクトのコピーを要求するたびに遅延が発生します。 これらの場合、別のパターンを使用できます。
DI(Dependency Injection)により、初期化中に必要な依存関係をコンテナーから自動的にプルできます。 つまり、IoCコンテナーを介して
MyWindow
を作成すると、DIメカニズムは、直接関与することなく
MyService
を魔法のように初期化できます。
どのように機能しますか?
プログラムには
Unityフレームワークを使用します。 開始するには、
Main()
書き換えます。その中にコンテナを作成し、DIをウィンドウに適用します。
public class MyProgram<br/>
{<br/>
static void Main()<br/>
{<br/>
⋮<br/>
var uc = new UnityContainer(); <br/>
Application.Run( uc.Resolve<MyWindow>() );<br/>
}<br/>
}<br/>
コンテナの
Resolve()
メソッドを使用して、タイプ
MyWindow
オブジェクトの作成だけでなく、
そのすべての依存関係の自動作成も要求します。 ここで、サービス(つまり、依存する部分)の作成を自動的に取得する方法を見てみましょう。 まず、サービスインターフェイスを引き出して、後で変更できるようにします。
interface IService<br/>
{<br/>
void DoSomething();<br/>
}<br/>
<br/>
public class MyService : IService<br/>
{<br/>
⋮ //
}<br/>
次に、インターフェースが使用されるように
MyWindow
を変更します。 コンテナが初期化するように、サービスへのリンクを追加する方法にはいくつかのオプションがあります。 それらの1つを次に示します。
public class MyWindow : Form<br/>
{<br/>
private IService service;<br/>
public MyWindow(IService service)<br/>
{<br/>
this .service = service;<br/>
}<br/>
}<br/>
あと1つだけ残っていることがあります
IService
型のオブジェクトのリクエストで
IService
を
IService
ようにコンテナに
IService
します。
public class MyProgram<br/>
{<br/>
static void Main()<br/>
{<br/>
⋮<br/>
var uc = new UnityContainer();<br/>
uc.RegisterType<IService, MyService>(); <br/>
Application.Run(uc.Resolve<MyWindow>());<br/>
}<br/>
}<br/>
それだけです!!! これで、プログラムが起動すると、変数
service
ウィンドウが
自動的に初期化され
ます 。 これは、コンストラクター注入と呼ばれます。 コンストラクターを空のままにしたいですか? お願い:
public class MyWindow : Form<br/>
{<br/>
[Dependency]<br/>
public IService Service { get; set; } <br/>
<br/>
public MyWindow()<br/>
{<br/>
⋮<br/>
}<br/>
}<br/>
フィールドをプロパティに変更し、
[Dependency]
属性でマークして、クラスを作成するときに初期化する必要があることをコンテナに示唆しました。 結果は、コンストラクターの場合と同じです。 この手法は「セッター注入」と呼ばれます。
以上です! ご清聴ありがとうございました! トピックに興味があり、サンクトペテルブルクに住んでいる場合は、明日の
会議に来てください。
シリーズのパート2を読む