7

Ich verwende den Autofac-IoC-Container mit dem MVC4-Add-On, das den Gültigkeitsbereich InstancePerHttpRequest bereitstellt. In meinem Projekt habe ich jedoch die Web-, Web-API- und Hintergrund-Worker-Threads. Im folgenden Beispiel nehme ich an, dass der InstancePerHttpRequest-Bereich nicht viel bedeutet, wenn er nicht von einer Webanforderung stammt.Können mehrere Autofac-Lebensdauerbereiche bei einer Registrierung angegeben werden?

Ich frage mich, ob es möglich ist, etwas wie das folgende Beispiel zu tun und den Container den am besten geeigneten lebenslangen Umfang wählen lassen?

builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>() 
    .InstancePerHttpRequest() 
    .InstancePerApiRequest() 
    .InstancePerDependency(); 

In diesem Fall, was ich zu geschehen beabsichtigt ist, wenn die Anforderung von einem Web-Anfrage stammt, dann wird es den InstancePerHttpRequest Umfang wählen, wenn es von einem WebAPI Anfrage stammt wird es den InstancePerApiRequest Umfang wählen und wenn es verwendet wird, durch die Anwendung Worker-Threads wird es den InstancePerDependency-Bereich verwenden?

Irgendwelche Ideen, wenn dies oder etwas Ähnliches möglich ist?
Dank

Antwort

10

Diese Frage hat einige ziemlich schwere Überschneidungen mit diesen:

Sie werden diejenigen überprüfen möchten heraus für einige Ideen.

Die kurze Antwort ist: Diese Art der Sache wird nicht aus der Box unterstützt. Sie müssen eines von ein paar Dingen tun.

Option: Sie könnten einen anderen Container für die Hintergrundthreads haben. Dadurch können Sie keine Singletons auf Anwendungsebene freigeben. Dies ist jedoch möglicherweise für Ihre Anwendung in Ordnung.

Option: Sie können zwei lebenslange Bereiche außerhalb des Containers erstellen und die verschiedenen Registrierungen als Teil des Aufrufs an BeginLifetimeScope ausführen. Dadurch können Sie Singletons auf Anwendungsebene freigeben und unterschiedliche Gültigkeitsbereiche für dieselben Komponenten in verschiedenen Kontexten verwenden. Es ist jedoch ein wenig schwieriger, die Registrierungen zu verwalten, und Sie benötigen zwei verschiedene Service-Locators (z. B. DependencyResolver), da jeder logische Kontext aus seinem eigenen Bereich aufgelöst werden muss.

var builder = new ContainerBuilder(); 
builder.RegisterType<AppLevelSingleton>().SingleInstance(); 
var container = builder.Build(); 

// Create a nested lifetime scope for your background threads 
// that registers things as InstancePerDependency, etc. Pass 
// that scope to whatever handles dependency resolution on the thread. 
var backgroundScope = container.BeginLifetimeScope(
    b => b.RegisterType<DatabaseFactory>() 
     .As<IDatabaseFactory>() 
     .InstancePerDependency()); 

// Create a nested lifetime scope for the web app that registers 
// things as InstancePerHttpRequest, etc. Pass that scope 
// as the basis for the MVC dependency resolver. 
var webScope = container.BeginLifetimeScope(
    b => b.RegisterType<DatabaseFactory>() 
     .As<IDatabaseFactory>() 
     .InstancePerHttpRequest()); 
var resolver = new AutofacDependencyResolver(webScope); 
DependencyResolver.SetResolver(resolver); 

Wenn Sie wirklich mit dieser Option erhalten Phantasie wollten, könnten Sie eine benutzerdefinierte implementieren IContainer, was Kontext ist es in und löst die Dinge aus dem entsprechenden verschachtelten Bereich erfassen kann. So funktioniert die mandantenfähige Autofac-Unterstützung. Allerdings ist das eine viel kompliziertere Lösung, also werde ich das hier nicht alles schreiben. Überprüfen Sie die Autofac-Quelle für die mandantenfähige Unterstützung für Beispiele.

Option: Sie könnten einen „kleinsten gemeinsamen Nenner“ Art Registrierung verwenden wie InstancePerDependency oder InstancePerLifetimeScope und überspringen die Vorstellung, eine ganz unterschiedliche Lebensdauer für die verschiedenen Teile der Anwendung zu haben.

Beachten Sie, dass, gerade jetzt, technisch, intern, gibt es keinen Unterschied zwischen dem, was InstancePerHttpRequest und InstancePerWebApiRequest tun. Sie beide laufen auf genau dasselbe hinaus und sind effektiv austauschbar. (Ich kann nicht versprechen, dass es immer so sein wird, aber ich weiß nicht, warum es sich ändern müsste.)

+0

Ehrfürchtig! Danke für die gründliche Antwort, das hilft sehr. – chriskopec

+0

denke, das wäre nützlich. Ein Beispiel ist die Verwendung von EF-Framework seit der dbcontext Web API-Aktion, wenn es Aufruf Klasse ist, die Zugriff auf die Datenbank mit einem neuen Thread benötigen, Chancen, wenn es nur instanceperhttprequest ist, wird es Ausnahme auslösen, so müssen die Flexibilität haben InstancePerLifetimeScope. es ist fast besser, nur InstancePerLifetimeScope zu haben. – koo9