2009-09-08 9 views
36

wie kann ich zwei verschiedene Schnittstellen in Einheit mit der gleichen Instanz registrieren ... Derzeit ichUnity Register, zwei Interfaces als ein Singleton

 _container.RegisterType<EventService, EventService>(new ContainerControlledLifetimeManager()); 
     _container.RegisterInstance<IEventService>(_container.Resolve<EventService>()); 
     _container.RegisterInstance<IEventServiceInformation>(_container.Resolve<EventService>()); 

bin mit dem funktioniert, aber nicht schön aussehen ..

Also, ich denke, Sie bekommen die Idee. EventService implementiert zwei Schnittstellen, ich möchte einen Verweis auf das gleiche Objekt, wenn ich die Schnittstellen auflösen.

Chris

+0

OK, Wenn dies der richtige Weg ist, behalte ich es einfach. War nur daran interessiert, ob es einen eleganteren Weg gab, aber es funktioniert, und das ist der Punkt. Ich mag wirklich die Einheit so weit ... ziemlich schön in Kombination mit PRISM –

+0

Sieh dir Sven's Antwort an ... es hat eine Menge Verdienst. Lesen Sie die Kommentare von @Chris Tavares auf meine Antwort für einige Details. Schau es dir an und wenn es dir gefällt, möchte ich dich bitten, das als Antwort für andere Leute zu markieren. –

Antwort

13

bearbeitet

Nach einigem Feedback in den Kommentaren habe ich entschieden, dass Sven Antwort eine viel bessere Antwort. Danke an Chris Tavares für den Hinweis auf die technischen Vorzüge.


Das ist so ziemlich die einzige Möglichkeit, es zu tun.

Man könnte es leicht ändern (I RegisterType mit der gleichen Art für jeden generischen Parameter hate):

EventService es = _container.Resolve<EventService>(); 
_container.RegisterInstance<IEventService>(es); 
_container.RegisterInstance<IEventServiceInformation>(es); 

Wenn ein oder mehrere Ihrer IoC Kinder wird den Beton EventService Typ (hoffentlich nicht) beantragen Sie würden einen weiteren RegisterInstance vom Typ RegisterInstance<EventService> hinzufügen. Hoffentlich brauchen Sie das nicht und alle abhängigen Objekte verlangen nach einer IEventService, anstatt einer EventService.

hoffe, das hilft, Anderson

+5

Es ist eine gute Praxis, bei Abhängigkeitsinjektionen die Verdrahtungszeit so weit wie möglich von der Auflösungszeit zu trennen. Diese Lösung hat den Nachteil, dass es erfordert, dass Sie Anrufe zu "lösen" mit Aufrufen von "Registrieren" mischen. –

+0

@Nigel Thorne: Im Allgemeinen ist das wahr, aber in diesem Fall hatte das OP einen Dienst, den er/sie registrieren musste viele Abhängigkeiten. Ich schlug Unity vor, dieses Objekt zu erstellen, so dass diese Abhängigkeiten automatisch aufgelöst wurden, so dass die Instanz für beide Registeraufrufe verwendet werden konnte (er/sie benötigte dieselbe Instanz, die für beide Schnittstellen zurückgegeben wurde). Normalerweise ist dies unerwünscht, aber in diesem Fall die einzige Möglichkeit, dies zu tun (abgesehen davon, dass das Objekt manuell instanziiert wird). –

+3

Das ist wirklich nicht der richtige Weg - benutzen Sie stattdessen Sven Kunzlers Antwort. –

51

[Bearbeiten]

Die Lösung für diese Konfiguration über XML tun können here finden. Auf der Grundlage dieser Antwort würde ich einen optimierten Code-only Ansatz vorschlagen, wie folgt:

_container.RegisterType<IEventService, EventService>(new ContainerControlledLifetimeManager()); 
_container.RegisterType<IEventServiceInformation, EventService>(new ContainerControlledLifetimeManager()); 
bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>()); 

Auf diese Weise sich die Event Klasse nicht vom Container veröffentlicht. Da die Klasse als Implementierungsdetail betrachtet werden sollte, ist dies der bevorzugte Ansatz.

[Original Antwort]

ein wenig zu spät eine Antwort, aber sollte es tun:

_container.RegisterType<EventService>(new ContainerControlledLifetimeManager()); 
_container.RegisterType<IEventService, EventService>(); 
_container.RegisterType<IEventServiceInformation, EventService>(); 

bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>()); 
+0

weiß jemand wie man dies durch konfiguration? – JML

+0

Ich würde auch gerne wissen, wie man das durch Konfiguration macht. – lukebuehler

+6

Interessanterweise (zumindest hier) scheint es, dass wenn eine davon als benannte Registrierung eingestellt wird, es nicht funktioniert ... – Reddog

0

Eine Lösung, die auch für benannte Instanzen arbeiten kann, ist die Adapter-Muster zu verwenden, zu erstellen Wegwerfadapter an die Schnittstelle, die die Singleton-Instanzen umschließen. Dann werden aufgelöste Instanzen immer an die Singleton-Instanz, event, wenn sie mit ResolveAll aufgelöst werden, gerichtet. Dies hilft, wenn ein Heap von Diensten vorhanden ist, die eine generische Schnittstelle wie IStartable oder etwas implementieren.

public class EventServiceAdapter<T> : IEventService where T : IEventService 
{ 
    private readonly T _adapted; 
    EventServiceAdapter(T adapted) 
    { 
     _adapted = adapted; 
    } 
    public string SomeMethod() 
    { 
     return _adapted.SomeMethod(); 
    } 
} 

Dann registrieren Sie den Schnittstellenadapter um Ihren registrierten Singletontyp.

_container 
    .RegisterType<EventService>(new ContainerControlledLifetimeManager()) 
    .RegisterType<IEventService, EventServiceAdapter<EventService>>("namedEventService"); 

Sie können dann jede Singleton hinter einer beliebigen Anzahl von Schnittstellen verstecken, und die Arbeit mit beiden auflösen und ResolveAll.

4

Der Adapteransatz schien für solch eine einfache Sache sperrig zu sein, also schaute ich ein bisschen weiter. Um das Problem mit den benannten Instanzen zu umgehen, müssen Sie den Typ registrieren und Factories für die Schnittstellen registrieren. aufgrund fehlender Abhängigkeiten

InjectionFactory factory = new InjectionFactory(x => x.Resolve<SimulationService>()); 
this.Container.RegisterType<SimulationService>(new ContainerControlledLifetimeManager()); 
this.Container.RegisterType<IContentProvider>("SimulationContentProvider", factory); 
this.Container.RegisterType<ISimulationService>(factory); 

Auf diese Weise brauchen Sie nicht eine Instanz der konkreten Klasse (bei Registrierung), die in meinem Fall nicht möglich war, zu schaffen.

Verwandte Themen