7

Unity をもう少し理解するためにいじってみたところ、次のシナリオに出くわしました。Resolve同じ型を 2 回登録し、1 つがシングルトンである場合、シングルトンのみが返されるように呼び出すにはどうすればよいでしょうか? これが一意の を使用して達成できることは理解していますが、これを使用Nameせずに実行できるかどうか疑問に思っています。

例えば:

_container.RegisterType<Music>(new InjectionConstructor(new Album("Non-singleton", "Non-singleton")));
_container.RegisterType<Music>(new ContainerControlledLifetimeManager());

と呼び出し

var music = Factory.Resolve<Music>();

「非シングルトン」オブジェクトを返します。最初は、登録順だと思っていましたが、切り替えてみると「非シングルトン」インスタンスが返ってきます。

これには理由がありますか?属性Resolveを指定せずに、同じコンテナー内の 2 つの登録済みオブジェクトのシングルトン タイプのみにする方法はありますか?Name

4

1 に答える 1

25

それを分解しましょう:

_container.RegisterType<Music>(new InjectionConstructor(
    new Album("Non-singleton", "Non-singleton")));

これにより、名前のない型 (null またはデフォルト) がコンテナーに登録され、型Musicを受け入れるコンストラクターを使用するように Unity に指示されますAlbumnew Album("Non-singleton", "Non-singleton")また、によって作成されたインスタンスを値として常にMusic(Album album)コンストラクターに渡します。したがって、すべてMusicのインスタンスに同じアルバムが注入されます。

_container.RegisterType<Music>(new ContainerControlledLifetimeManager());

Musicこれは、名前のないタイプ (null またはデフォルト)に基づいて登録を実行します。指定された InjectionMembers がないため、既存の登録への唯一の変更は、ライフタイム マネージャーを追加することです。BuildKey (Type: Music、Name: null) が両方の RegisterType 呼び出しで同じであるため、既存の登録が更新されます。

unityContainer.RegisterType<Music>(new InjectionConstructor(new Album("Non-singleton", "Non-singleton")));

unityContainer.RegisterType<Music>(new ContainerControlledLifetimeManager());

var music = unityContainer.Resolve<Music>();
var music2 = unityContainer.Resolve<Music>();

bool areEqual = ReferenceEquals(music, music2);

上記の areEqual は true であるため、単一のインスタンスが返されます。

Name 属性を指定せずに、同じコンテナー内の 2 つの登録済みオブジェクトのシングルトン タイプのみを解決する方法はありますか?

タイプはタイプと名前で登録されるため、同じタイプを複数登録する唯一の方法は、名前を使用することです。

// Named registration
unityContainer.RegisterType<Music>("NonSingleton Name",
    new InjectionConstructor(new Album("Non-singleton", "Non-singleton")));

// Default (null) registration
unityContainer.RegisterType<Music>(new ContainerControlledLifetimeManager());

最初の登録をオーバーライドしたい場合は、新しい InjectionConstructor を指定することでそれを行うことができます。これにより、ビルド プランがクリアされ、コンストラクターの選択ポリシーが設定されます。

unityContainer.RegisterType<Music>(new InjectionConstructor(
    new Album("Non-singleton", "Non-singleton")));

unityContainer.RegisterType<Music>(new ContainerControlledLifetimeManager(),
    new InjectionConstructor(new Album("singleton", "singleton")));

補足として、依存関係 (この場合はアルバム) が本当に定数値でない限り、通常はレジスタ型呼び出し内にハードコーディングしません。それでも、定数インスタンスをシングルトンとして登録し、コンテナーに解決させたい場合があります。

興味深い質問は、Unity がデフォルトのコンストラクター選択ポリシーを使用するように、最初の RegisterType 呼び出しの後にコンストラクター選択ポリシーをリセットする方法です。これは、コンストラクターの選択ポリシーをクリアするカスタム InjectionMember で行うことができます。

unityContainer.RegisterType<Music>(new InjectionConstructor(
    new Album("Non-singleton", "Non-singleton")));

unityContainer.RegisterType<Music>(new ContainerControlledLifetimeManager(),
    new ClearInjectionConstructor());

public class ClearInjectionConstructor : InjectionMember
{
    public override void AddPolicies(Type serviceType, 
        Type implementationType, 
        string name, 
        Microsoft.Practices.ObjectBuilder2.IPolicyList policies)
    {
        policies.Clear<IConstructorSelectorPolicy>(
            new NamedTypeBuildKey(implementationType, name));
    }
}
于 2013-08-17T15:58:25.123 に答える