6

Bawiłem się z Unity, aby zrozumieć to nieco więcej, i natknąłem się na następujący scenariusz. Jeśli miałbym zarejestrować dwa razy ten sam typ, ale jeden jest singletonem, jak mogę zadzwonić pod numer Resolve, aby zwrócić tylko singleton? Rozumiem, że można to osiągnąć za pomocą unikalnego Name, ale zastanawiam się, czy można to zrobić bez.Zachowanie jedności przy dwukrotnym rejestrowaniu tego samego typu i rozwiązywaniu tylko singletona

Na przykład:

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

i nazywając

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

zwraca 'Non-singleton' obiekt. Początkowo myślałem, że jest to oparte na zamówieniu rejestracyjnym, ale przełączając się, nadal otrzymuję instancję "Non-singleton".

Czy istnieje ku temu powód? Czy istnieje sposób, aby Resolve tylko typ singleton dla dwóch zarejestrowanych obiektów w tym samym kontenera w/out określając atrybut Name?

Odpowiedz

21

Złammy go:

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

ten rejestruje się w pojemniku można sprawdzić rodzaj Music bez nazwy (null lub domyślna) i mówi jedność użyć konstruktora, który akceptuje typ Album. Również zawsze przekazuj instancję utworzoną przez new Album("Non-singleton", "Non-singleton") jako wartość do konstruktora Music(Album album). Tak więc każda instancja Music będzie miała wstrzyknięty ten sam Album.

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

ten wykonuje rejestrację na podstawie typu Music bez nazwy (NULL lub domyślne). Ponieważ nie określono żadnego InjectionMembers, jedyną zmianą w istniejącej rejestracji jest dodanie menedżera życia. Istniejąca rejestracja jest aktualizowana, ponieważ klucz BuildKey (Type: Music, Name: null) jest taki sam dla obu wywołań 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); 

W powyższym areEqual wprawdzie tak jeden przykład jest zwracany.

Czy istnieje sposób rozstrzygnięcia tylko typu singleton dla dwóch zarejestrowanych obiektów w tym samym pojemniku bez określania atrybutu Nazwa?

typy są rejestrowane przez rodzaj i nazwa więc jedynym sposobem, aby mieć wiele rejestracje dla tego samego typu jest użycie nazwy:

Teraz, jeśli chcesz nadpisać pierwszej rejestracji można zrobić przez określenie nowego InjectionConstructor. Spowoduje to wyczyszczenie planu kompilacji i ustawienie zasad wyboru konstruktora.

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

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

Na marginesie, to zazwyczaj nie trudno kod zależność (w tym przypadku album) wewnątrz zaproszenia typu rejestr chyba to było naprawdę wartością stałą. Nawet wtedy możesz chcieć zarejestrować stałą instancję jako pojedynczą i pozwolić pojemnikowi rozwiązać ją za Ciebie.

Interesujące pytanie brzmi: jak zresetować zasady wyboru konstruktora po pierwszym wywołaniu RegisterType, aby Unity użyło swojej domyślnej zasady wyboru konstruktora. Można to zrobić za pomocą niestandardowego elementu InjectionMember, który usuwa zasady wyboru konstruktora:

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)); 
    } 
} 
Powiązane problemy