もう一度、メガコンプレックスサービスを作成しましょう。
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
がクラスの場合、次のように書くこともできます。
Unityに、「空の」コンストラクターを使用する必要があることを示唆しました。 さて、新しい機能を試してみましょう:class Random<br/>
{<br/>
[InjectionConstructor]<br/>
Random() { }<br/>
⋮<br/>
}<br/>
値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
の作成を制御する必要があります。
これらはすべてデザイナーの明らかな操作でした。より複雑な例を見てみましょう。 2つのサービスがあり、どちらもuc.RegisterType<IService, MyService>(<br/>
new InjectionConstructor(<br/>
new InjectionParameter(10)));<br/>
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/>