6

Bir süredir bunu anlamak için Unity ile uğraştım ve aşağıdaki senaryoya rastladım. Aynı tipi iki kez kaydettirecek olsaydım, ama tek bir single'la Resolve'u nasıl arayabilirim, böylece yalnızca singleton döndürülür? Bunun, benzersiz bir Name kullanarak gerçekleştirilebileceğini anlıyorum, ancak bu olmadan yapılabilir mi diye merak ediyorum. ÖrneğinAynı türün iki kez kaydedilmesi ve yalnızca tekil özümün çözülmesi için bir davranış davranışı

:

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

ve

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

Non-tekil 'nesnesi geri arama. İlk başta, kayıt sırasına göre yapıldığını düşündüm, ancak bunu değiştirdiğimde hala 'Tekil olmayan' örneğini alıyorum.

Bunun için bir neden var mı? Resolve'un yalnızca Name özniteliğini belirterek aynı kapsayıcıdaki iki kayıtlı nesne için singleton türünün bir yolu var mı?

cevap

21

en yıkmak edelim:

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

Bu konteyner isimsiz tip Music (null veya varsayılan) ile kaydeder ve bir tür Album kabul kurucusunu kullanmak Unity söyler. Ayrıca, her zaman new Album("Non-singleton", "Non-singleton") tarafından oluşturulan örneği Music(Album album) yapıcısına değer olarak iletmek. Yani her bir Music örneğinin içine aynı Albüm yerleştirilmiş olacaktır.

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

Bu isimsiz (null veya varsayılan) ile tip Music dayalı bir kayıt gerçekleştirir. Çünkü, herhangi bir InjectionMembers bulunmadığı için mevcut kayıttaki tek değişiklik ömür boyu bir yönetici eklemektir. BuildKey (Tür: Müzik, İsim: null), hem RegisterType çağrıları için aynı olduğundan mevcut kayıt güncellenir.

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); 

YukarıdakilerEqual doğrudur, dolayısıyla tek bir örnek döndürülür.

Aynı kapsayıcıdaki iki kayıtlı nesne için yalnızca tekil tipini Çözümleme bir yol özniteliği belirterek bir yolu var mı? Şimdi

yapabileceğin ilk kayıt geçersiz istiyorsa: Aynı tip bir isim kullanmaktır için tek yol birden kayıtlarını olması çok

Türleri Tip ve Ada Göre kayıtlıdır Yeni bir InjectionConstructor belirterek. Bu, yapı planını temizler ve kurucu seçim politikasını belirler. Bir yan not olarak

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

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

, olur genellikle sert kod gerçekten sabit bir değer sürece kayıt tipi çağrısı içindeki (bu durumda Albüm olarak) bağımlılığı. O zaman bile, sabit örneği tekil olarak kaydedip kapsayıcıyı sizin için çözmesini isteyebilirsiniz.

İlginç bir soru, ilk RegisterType çağrısından sonra kurucu seçim ilkesini nasıl sıfırlarsınız? Böylece Unity, varsayılan kurucu seçim ilkesini kullanır. Bunu, yapıcı seçim ilkesini temizleyen özel bir InjectionMember ile yapabilirsiniz:

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)); 
    } 
}