初心者向けの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/>
今のところすべてです。 続く!

Source: https://habr.com/ru/post/J63280/


All Articles