初心者向けのDIおよびIoC、パート2

DI / IoCのトピック続けて、重要なオブジェクト構成スクリプトでUnityを使用する複雑な例を見ていきます。



もう一度、メガコンプレックスサービスを作成しましょう。



public class MyService<br/>

{<br/>

[Dependency]<br/>

public Random MyRandom { get; set; }<br/>

}<br/>

<br/>

⋮<br/>

<br/>

var uc = new UnityContainer();<br/>

var svc = uc.Resolve<MyService>();<br/>

Console.WriteLine(svc.MyRandom.Next());<br/>





Random



は空の呼び出し(つまり、 new Random()



)を行う必要があるという明らかな事実にもかかわらず、DIを介してRandom



タイプのオブジェクトを作成しようとすると失敗しますが、最も「トリックされた」ものを呼び出して苦しみます失態。 修正方法 このようなもの:



// Random

uc.RegisterType<Random>( new InjectionConstructor());<br/>





Random



がクラスの場合、次のように書くこともできます。



class Random<br/>

{<br/>

[InjectionConstructor]<br/>

Random() { }<br/>

⋮<br/>

}<br/>





Unityに、「空の」コンストラクターを使用する必要があることを示唆しました。 さて、新しい機能を試してみましょう:



var svc = uc.Resolve<MyService>();<br/>

var svc2 = uc.Resolve<MyService>();<br/>

Console.WriteLine(<br/>

ReferenceEquals(svc.MyRandom, svc2.MyRandom));<br/>





False



はコンソールに書き込まれます コンテナのデフォルトの動作は、毎回新しいオブジェクトを作成することです。 原則として、プロジェクト全体で1つのPark-and-Millerovsky Random



で十分であると思われる場合、シングルトンを取得する方法は? はい、とても簡単です:



uc.RegisterType<Random>(<br/>

new ContainerControlledLifetimeManager(),<br/>

new InjectionConstructor());<br/>

var svc = uc.Resolve<MyService>();<br/>

var svc2 = uc.Resolve<MyService>();<br/>

Console.WriteLine(<br/>

ReferenceEquals(svc.MyRandom, svc2.MyRandom));<br/>





このコードは、すでにTrue



コンソールに書き込まれます。 LifetimeManager



から継承するパラメーターは、オブジェクトが存続する期間を決定します。 たとえば、スレッド/セッション/コールごとに新しいオブジェクトが発行されるように、必要に応じてそれを継承すると便利です。



ご想像のとおり、DIは参照型に対してのみ自動的に機能します。 以下のコードは機能しません。



public interface IService<br/>

{<br/>

int GetN();<br/>

}<br/>

<br/>

public class MyService : IService<br/>

{<br/>

public int n;<br/>

public MyService( int n)<br/>

{<br/>

this .n = n;<br/>

}<br/>

public int GetN() { return n; }<br/>

}<br/>

⋮<br/>

var uc = new UnityContainer();<br/>

uc.RegisterType<IService, MyService>();<br/>

uc.RegisterType< int >( new InjectionConstructor(10));<br/>

var svc = uc.Resolve<IService>();<br/>

Console.Write(svc.GetN());<br/>





残念ながら、 System.Int32



はコンストラクターがなかったため、問題なくコンパイルされるこのコードは機能しません。 実際、間違った属性を選択しただけですInt32



の作成を操作する代わりに、この場合、 IService



の作成を制御する必要があります。



uc.RegisterType<IService, MyService>(<br/>

new InjectionConstructor(<br/>

new InjectionParameter(10)));<br/>





これらはすべてデザイナーの明らかな操作でした。より複雑な例を見てみましょう。 2つのサービスがあり、どちらもIService



実装するとします。



public interface IService<br/>

{<br/>

void DoSomething();<br/>

}<br/>

public class MyService : IService<br/>

{<br/>

public void DoSomething()<br/>

{<br/>

Console.WriteLine( "My service" );<br/>

}<br/>

}<br/>

public class OtherService : IService<br/>

{<br/>

public void DoSomething()<br/>

{<br/>

Console.WriteLine( "Other service" );<br/>

}<br/>

}<br/>





次に、これらのサービスを使用するクラスを作成します。



public class Consumer<br/>

{<br/>

IService[] services;<br/>

public Consumer(IService[] services)<br/>

{<br/>

this .services = services;<br/>

}<br/>

public void DoEverything() <br/>

{<br/>

foreach ( var s in services)<br/>

s.DoSomething();<br/>

}<br/>

}<br/>





Consumer



を解決してDoEverything



うとしても、何もDoEverything



ませんDoEverything



は、 IService



を登録されたすべてのIService



タイプの抽出として予約して、 new IService[0]



をコンストラクターに渡すのが良いとは考えていません。 コンテナは再び助けなければなりません:



uc.RegisterType<Consumer>( new InjectionConstructor(<br/>

new ResolvedParameter<IService[]>()));<br/>





今のところすべてです。 続く!



All Articles