Mit Einfachen Injektor mit SignalR
Ich dachte, mit meinen eigenen IoC wäre ziemlich straight-forward mit SignalR und vielleicht ist es; wahrscheinlich mache ich etwas falsch. Hier ist mein code, den ich bisher:
private static void InitializeContainer(Container container)
{
container.Register<IMongoHelper<UserDocument>, MongoHelper<UserDocument>>();
//... registrations like about and then:
var resolver = new SimpleInjectorResolver(container);
GlobalHost.DependencyResolver = resolver;
}
dann meine Klasse:
public class SimpleInjectorResolver : DefaultDependencyResolver
{
private Container _container;
public SimpleInjectorResolver(Container container)
{
_container = container;
}
public override object GetService(Type serviceType)
{
return _container.GetInstance(serviceType) ?? base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
return _container.GetAllInstances(serviceType) ?? base.GetServices(serviceType);
}
}
Was am Ende passiert ist, bekomme ich eine Fehlermeldung, dass IJavaScriptProxyGenerator nicht gelöst werden kann, so dass ich denke, ich werde fügen Sie der Anmeldung:
container.Register<IJavaScriptProxyGenerator, DefaultJavaScriptProxyGenerator>(
ConstructorSelector.MostParameters);
aber dann gibt es ein Bündel von anderen! Ich bekomme:
container.Register<IDependencyResolver, SimpleInjectorResolver>();
container.Register<IJavaScriptMinifier, NullJavaScriptMinifier>();
container.Register<IJavaScriptProxyGenerator, DefaultJavaScriptProxyGenerator>(
ConstructorSelector.MostParameters);
container.Register<IHubManager, DefaultHubManager>();
container.Register<IHubActivator, DefaultHubActivator>();
container.Register<IParameterResolver, DefaultParameterResolver>();
container.Register<IMessageBus, InProcessMessageBus>(ConstructorSelector.MostParameters);
Die gibt mir immer noch "Keine Registrierung für Typ ITraceManager
gefunden werden konnte." ... aber nun Frage ich mich, ob ich das Tue Recht, wie ich gehofft, ich würde nicht brauchen, um re-wire alles SignalR ist zu tun...richtig? Hoffentlich? Wenn nicht, behalte ich entlang stapfen, aber ich bin SignalR und Einfache Injektor-newb, so dachte, ich würde zuerst Fragen. 🙂
Zusätzliche: https://cuttingedge.it/blogs/steven/pivot/entry.php?id=88 seit SignalR hatte mehrere Konstruktoren.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gut, ich versuchte gestern und ich eine Lösung gefunden habe.
Nach mir, der einzige moment, wo ich will, dependency injection in SignalR ist für meine Naben: I don ' T care darüber, wie SignalR arbeiten im inneren !
Also anstatt Sie zu ersetzen die DependencyResolver, habe ich meine eigene Implementierung von IHubActivator :
Dass ich registrieren kann, wie dies (in Application_Start) :
return (IHub)DependencyResolver.Current.GetService(descriptor.HubType);
RouteTable.Routes.MapHubs();
? Diese Zeile verstehe ich nicht. Wenn ich es weglassen, es funktioniert auch wie ein Zauber.Werfen möchte, meine 2 cents in hier mit den anderen Antworten, die hilfreich sein kann bei der Suche nach Ihrem eigenen Weg mit dependency injection in SignalR, entweder mit SimpleInjector oder anderen IoC.
Mit @Steven ' s Antwort
Wenn Sie sich entscheiden, zu verwenden, Steven, Antwort, stellen Sie sicher, Sie registrieren Ihre hub-Routen vor, die Sie verfassen, die Wurzel. Die
SignalRRouteExtensions.MapHubs
Erweiterung Methode (ein.k.ein.routes.MapHubs()
) rufenRegister(Type, Func<object>)
auf dieGlobalHost.DependencyResolver
wenn die Zuordnung der hub-Routen, so dass, wenn Sie die swap -DefaultDependencyResolver
mit StevenSimpleInjectorResolver
vor den Routen zugeordnet sind, führen Sie in seineNotSupportedException
.Mit @Nathanael Marchands Antwort
Dies ist mein Favorit. Warum?
SimpleInjectorDependencyResolver
.DefaultDependencyResolver
(ein.k.ein.GlobalHost.DependencyResolver
), das bedeutet noch weniger code.DefaultDependencyResolver
, es wird "einfach funktionieren".Wie Nathanael sagte aber, dies ist nur, wenn Sie kümmern sich um die Abhängigkeiten, die auf Ihrem
Hub
Klassen, die wahrscheinlich der Fall für die meisten. Wenn Sie zu verwirren wollen um mit dem Einspritzen anderen Abhängigkeiten in SignalR, möchten Sie vielleicht zu gehen mit Steven ' s Antwort.Probleme mit pro web-Anfrage Abhängigkeiten in einer
Hub
Es ist eine interessante Sache über SignalR... wenn sich ein client trennt die Verbindung zu einem hub (zum Beispiel durch schließen Ihres browser-Fensters), wird eine neue Instanz der
Hub
Klasse in der Reihenfolge zu berufenOnDisconnected()
. Wenn dies geschieht,HttpContext.Current
null ist. Also, wenn diesHub
irgendwelche Abhängigkeiten hat, die registriert sind, pro web-Anfrage, irgendwas wird wohl schief gehen.In Ninject
Habe ich ausprobiert, SignalR dependency injection mit Ninject und die ninject-signalr-dependency resolver auf nuget. Mit dieser Konfiguration, Abhängigkeiten gebunden sind
.InRequestScope()
erstellt werden transient, wenn Sie injiziert in eineHub
während ein trennen-Ereignis. DaHttpContext.Current
null ist, ich nehme an, Ninject nur entscheidet, Sie zu ignorieren, und erstellen transiente Instanzen, ohne Ihnen zu sagen. Vielleicht gab es eine Konfigurationseinstellung zu sagen, ninject, Sie zu warnen, aber es war nicht der Standard.In SimpleInjector
SimpleInjector auf der anderen Seite wird eine exception werfen, wenn ein
Hub
hängt von einer Instanz registriert mitWebRequestLifestlyle
:...Hinweis: diese Ausnahme wird nur sprudeln, wenn
HttpContext.Current == null
ist, soweit ich das beurteilen kann, passiert das nur, wenn SignalR Anfragen einHub
Instanz, um zum aufrufenOnDisconnected()
.Lösungen für pro web-Anfrage Abhängigkeiten in einer
Hub
Beachten Sie, dass keines dieser sind wirklich ideal, es wird alles hängt von den Anforderungen Ihrer Anwendung.
In Ninject
Wenn Sie brauchen, non-transient-Abhängigkeiten, nicht nur überschreiben
OnDisconnected()
oder etwas zu tun, benutzerdefinierte es mit der Klasse Abhängigkeiten. Wenn Sie tun, jede Abhängigkeit im Diagramm wird eine separate (transient) Instanz.In SimpleInjector
Benötigen Sie eine hybrid-lifestyle zwischen
WebRequestLifestlye
und entwederLifestyle.Transient
,Lifestyle.Singleton
oderLifetimeScopeLifestyle
. WennHttpContext.Current
ist nicht null, Abhängigkeiten, die nur so lange Leben, wie die web-Anfrage, wie Sie normalerweise erwarten würden. Allerdings, wennHttpContext.Current
null ist, Abhängigkeiten werden entweder injiziert werden transient, als singletons oder innerhalb einer Lebensdauer Anwendungsbereich.Mehr über
LifetimeScopeLifestyle
In meinem Fall, ich habe eine EntityFramework
DbContext
Abhängigkeit. Diese kann tückisch sein, weil Sie zeigen Probleme bei der Anmeldung vorübergehend oder als singletons. Wenn Sie registriert sind transient, können Sie am Ende mit Ausnahmen beim Versuch, die Arbeit mit den Einheiten angebracht, um 2 oder mehrDbContext
Instanzen. Wenn registriert als ein singleton, dass Sie am Ende mit mehr Allgemeinen Ausnahmen (nicht immer registrieren Sie einenDbContext
als singleton). In meinem Fall brauchte ich dieDbContext
Leben in einem bestimmten Leben, in dem die selbe Instanz wiederverwendet werden kann über viele geschachtelte Operationen, was bedeutet, ich brauchte dieLifetimeScopeLifestyle
.Nun, wenn du mit dem hybrid-code oben mit dem
falseLifestyle: new LifetimeScopeLifestyle()
line, bekommen Sie eine weitere Ausnahme, wenn Ihre benutzerdefinierteIHubActivator.Create
- Methode wird ausgeführt:Den Weg, Sie haben eine Lebensdauer scoped Abhängigkeit geht so:
Alle Abhängigkeiten eingetragen sind, mit lifetime Umfang gelöst werden müssen innerhalb dieses
using
block. Außerdem, wenn eine dieser Abhängigkeiten implementierenIDisposable
Sie entsorgt werden, die am Ende derusing
block. Nicht versucht sein, so etwas zu tun:Fragte ich Steven (wer kommt auch zu dem SimpleInjector Autor in Fall, dass Sie nicht wissen) darüber, und er sagte:
Können Sie nicht verwenden
IHubActivator
um den Umfang der Abhängigkeiten, weil Sie nicht so lange Leben wie dieHub
Instanz, die es schafft. Also, auch wenn Sie verpackt dieBeginLifetimeScope()
Methode in einerusing
block, Ihre Abhängigkeiten entsorgt werden unmittelbar nach derHub
Instanz erstellt. Was Sie wirklich brauchen, hier ist eine andere Ebene der Dereferenzierung.Was ich am Ende mit, mit viel Dank an Steven helfen, ist ein Befehl decorator (und eine Abfrage decorator). Ein
Hub
kann nicht davon abhängen, pro web-request-Instanzen selbst, sondern muss abhängig von einem anderen Schnittstelle, deren Umsetzung hängt von der per-request-Instanzen. Die Umsetzung eingespritzt wird, in dieHub
Konstruktor ist eingerichtet (über simpleinjector) mit einem wrapper, der beginnt und über die Lebensdauer Anwendungsbereich.... es ist die dekorierte
ICommandHandler<T>
Instanzen abhängen, die pro-web-request-Instanzen. Für mehr Informationen über das Muster, das verwendet wird, Lesen Sie diese und diese.Beispiel Registrierung
RegisterManyForOpenGeneric
, dann schmücken Sie mitRegisterDecorator
vorbei an derCommandLifetimeScopeDecorator
. Sie können tatsächlich ändern Sie den code oben zu verwendenICommandHandler<TCommand>
statt einerFunc<ICommandHandler<TCommand>>
und es wird noch Spritzen. Es wird nur injizieren Sie die Instanz anstelle eines Delegaten zu faul injizieren Sie die Instanz. Ich habe aktualisiert die Antwort mit einem Beispiel.ExecutionContext
lebensstil, brauchen Sie noch Ihren hybrid-lifestyle? Seine gut zu Lesen trotzdem!UPDATE Dieser Antwort wurde aktualisiert für SignalR version 1.0
Dies ist, wie zu bauen, SignalR
IDependencyResolver
für Einfache Injektor:Leider gibt es ein Problem mit dem design der
DefaultDependencyResolver
. Das ist, warum die Umsetzung oben nicht Erben, sondern umschließt es. Ich habe eine Frage über diese auf die SignalR-Website. Sie können darüber Lesen Sie hier. Obwohl der designer stimmte mir zu, leider ist das Problem noch nicht behoben wurde in der version 1.0.Ich hoffe, das hilft.
Von SignalR 2.0 (und die beta) es ist eine neue Art der Einstellung der dependency resolver. SignalR verschoben OWIN startup um die Konfiguration. Mit Einfach Injektor-Sie würde es so machen:
Müsstest du explizit Spritzen Sie Ihre hubs so:
Diese config läuft live auf einem high-traffic-website ohne Probleme.
GetServices
Methode. Der code überprüftGetRegistration(serviceType, false) != null
, aber dieses Prädikat wird in der Regel Ausbeute falsch, da eine Registrierung für eine Sammlung ist eine andere Registrierung. DabeiGetRegistration(typeof(IEnumerable<>).MakeGenericType(serviceType), false) != null
allerdings wird nicht funktionieren, da das nie null zurückgeben (da Einfache Injektor macht diese Registrierung für Sie, wenn Sie fehlt). So blueling Antwort ist viel besser.Container
IhrStartup
Klasse?Container
Beispiel in dem folgenden Stück code:var config = new HubConfiguration() { Resolver = new SignalRSimpleInjectorDependencyResolver(Container) };
Folgende für mich gearbeitet. Darüber hinaus registrieren Sie einen Delegaten mit der container für Ihre hub-Klasse, vor dem instanziieren der dependency resolver.