Gemischter lifestyle für Pro Thread und Pro Web-Anfrage mit Einfach Injektor
Ich bin mit SimpleInjector
als mein IoC-Bibliothek. Ich melde mich DbContext
als pro web-Anfrage, und es funktioniert gut. Aber es ist eine Aufgabe, die ich ausführen es in einem hintergrund-thread. Also, ich habe ein problem zu schaffen DbContext
Instanzen. z.B.
Service1
hat eine Instanz vonDbContext
Service2
hat eine Instanz vonDbContext
Service1
undService2
ausführen von hintergrund-thread.Service1
holt ein Unternehmen und übergeben es anService2
Service2
verwendet, die Einheit, aber Einheit ist losgelöst vonDbContext
Eigentlich das problem ist hier: Service1.DbContext
ist der Unterschied von Service2.DbContext
.
Scheint es, wenn ich ausführen einer Aufgabe in einem separaten thread in ASP.NET MVC SimpleInjector
erstellt eine neue Instanz von DbContext
für jeden Anruf. Während einige IoC-Bibliotheken (zum Beispiel StructureMap
) haben eine gemischte Lebensweise für die pro-thread-pro-webrequest, es scheint SimpleInjector
noch nicht ein. Bin ich im Recht?
Haben Sie irgendeine Idee, um dieses problem zu lösen in SimpleInjector
?
Vielen Dank im Voraus.
EDIT:
Meine Dienstleistungen sind hier:
class Service1 : IService1 {
public Service1(MyDbContext context) { }
}
class Service2 : IService2 {
public Service2(MyDbContext context, IService1 service1) { }
}
class SyncServiceUsage {
public SyncServiceUsage(Service2 service2) {
//use Service2 (and Service1 and DbContext) from HttpContext.Current
}
}
class AsyncServiceUsage {
public AsyncServiceUsage(Service2 service2) {
//use Service2 (and Service1 and DbContext) from background thread
}
}
public class AsyncCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand> where TCommand : ICommand {
private readonly Func<ICommandHandler<TCommand>> _factory;
public AsyncCommandHandlerDecorator(Func<ICommandHandler<TCommand>> factory) {
_factory = factory;
}
public void Handle(TCommand command) {
ThreadPool.QueueUserWorkItem(_ => {
//Create new handler in this thread.
var handler = _factory();
handler.Handle(command);
});
}
}
void InitializeSimpleInjector() {
register AsyncCommandHandlerDecorator for services (commands actually) that starts with "Async"
}
Ich Benutzer Service2
manchmal und AsyncService2
anderen Zeiten.
- Verwandte: stackoverflow.com/questions/11041601/...
- Verwandte: stackoverflow.com/questions/10304023/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das Verhalten der
RegisterPerWebRequest
lebensstil der Einfachen Injector v1.5 und unten ist um wieder eine transiente Instanz, wenn Instanzen werden gebeten, außerhalb des Kontextes eines web-Anfrage (woHttpContext.Current
null ist). Rückkehr eine transiente Instanz wurde ein design-Fehler in Einfache Injektor, da dies macht es leicht zu verstecken unsachgemäße Nutzung. Die Version 1.6 von der Einfachen Injektor wird eine exception werfen, statt falsch Rückkehr eine transiente Instanz, klar zu kommunizieren, dass Sie falsch konfiguriert ist der container.Ist es richtig, dass Einfache Injektor hat keine integrierte Unterstützung für gemischte Lebensstile, wegen ein paar Gründen. Zunächst einmal ist es durchaus ein exotisches feature, das nicht viele Menschen brauchen. Zweitens, können Sie mischen zwei oder drei Lebensstile zusammen, das wäre also fast eine endlose Kombination von Hybriden. Und zuletzt, es ist (ziemlich) einfach anmelden, selbst.
Obwohl Sie können mischen Pro Web-Anfrage mit Pro Thread Lebensstile, wäre es wahrscheinlich besser, wenn Sie sich mischen, die Pro Web-Anfrage mit Pro Lebensdauer Rahmen, da mit der Lebensdauer Bereich, den Sie explizit starten und beenden Sie den Umfang (und können über die
DbContext
wenn der scope endet).Vom Einfache Injektor 2 und auf, Sie können leicht mischen Sie eine beliebige Anzahl von Lebensstilen zusammen mit der Lifestyle.CreateHybrid Methode. Hier ist ein Beispiel:
Es ist ein weiterer Stackoverflow-Frage, die in diesem Thema ein bisschen tiefer, möchten Sie vielleicht einen Blick: Einfache Injektor: multi-threading in MVC3 ASP.NET
UPDATE
Über Ihr update. Sie sind fast da. Die Befehle, die auf einem hintergrund-thread ausgeführt werden müssen, innerhalb einer Lebensdauer Anwendungsbereich, so müssen Sie explizit starten. Der trick ist hier zu nennen
BeginLifetimeScope
neuen thread auf, aber vor der eigentlichen Befehls-handler (und Ihre Abhängigkeiten) erstellt. In anderen Worten, der beste Weg, dies zu tun, ist in einen decorator.Die einfachste Lösung ist ein update Ihrer
AsyncCommandHandlerDecorator
zum hinzufügen von Rahmen:Puristen, für die SOLID Prinzipien zu Schreien, dass diese Klasse gegen die Prinzip Der Einzigen Verantwortung, da dieser Dekorator beide Befehle ausgeführt werden, in einem neuen thread und beginnt ein neues Leben Umfang. Ich würde nicht zu viel sorgen, da ich denke, dass es eine enge Beziehung zwischen dem starten einer hintergrund-thread starten und Lebensdauer Umfang (verwenden Sie nicht das eine ohne das andere sowieso). Aber immer noch, Sie könnte leicht lassen Sie die
AsyncCommandHandlerDecorator
unberührt und erzeugen eine neueLifetimeScopedCommandHandlerDecorator
wie folgt:Die Reihenfolge in der die Dekoratoren registriert werden, von natürlich essentiell, da die
AsyncCommandHandlerDecorator
muss wickeln Sie dieLifetimeScopedCommandHandlerDecorator
. Dies bedeutet, dass dieLifetimeScopedCommandHandlerDecorator
Registrierung muss zuerst kommen:Diese alte Stackoverflow-Frage spricht über diese im detail. Sie sollten definitiv einen Blick.
SimpleInjector
Ruf. Viel GlückService1
undService2
Objekte, die verwendet werden, in die beide Haupt-thread (web-Anfrage) und ein hintergrund-thread. Ich möchte in der Lage sein, dies zu tun. Und ich SpritzenDbContext
Ihnen durch die ctor-injection. Sollte ich ändern, um meine Implementierung?