7

Używam kontenera IoC Autofac z dodatkiem MVC4, który zapewnia zakres życia instancePerHttpRequest. Jednak w ramach mojego projektu mam wątki web, api i api. W poniższym przykładzie zakładam, że zasięg InstancePerHttpRequest nie ma większego znaczenia, jeśli nie pochodzi z żądania internetowego.Czy w rejestracji można określić wiele zakresów życia w Autofac?

builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>() 
    .InstancePerHttpRequest() 

Zastanawiam się, czy można zrobić coś podobnego do poniższego przykładu i czy kontener wybiera najbardziej odpowiedni zakres życia?

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

W tym przypadku, co mam zamiar się zdarzyć, jeżeli żądanie pochodzi od żądania sieci to będzie wybrać InstancePerHttpRequest zakres, jeżeli pochodzi od żądania WebAPI to dobrania InstancePerApiRequest zakres i jeśli jest ona wykorzystywana przez wątki robota aplikacji użyje zasięgu InstancePerDependency?

Jakieś pomysły, jeśli to lub coś podobnego jest możliwe?
Dzięki

Odpowiedz

10

To pytanie ma pewne dość ciężki zachodząc nich:

Będziemy chcieli, aby sprawdzić te out dla niektórych pomysłów.

Krótka odpowiedź brzmi: Tego rodzaju rzeczy nie są obsługiwane po wyjęciu z pudełka. Musisz zrobić jedną z kilku rzeczy.

Opcja: Możesz mieć inny pojemnik dla wątków tła. To nie pozwala na udostępnianie pojedynczych poziomów aplikacji, ale to może być w porządku dla twojej aplikacji.

Opcja: Można utworzyć dwa przedziały czasowe z kontenera i wykonać różne rejestracje w ramach połączenia z numerem BeginLifetimeScope. To umożliwiłoby udostępnianie pojedynczych poziomów aplikacji i ma różne zasięgi życia dla tych samych składników w różnych kontekstach. Trochę trudniej jest zarządzać rejestracjami i potrzebujesz dwóch różnych lokalizatorów usług (np. DependencyResolver), ponieważ każdy kontekst logiczny musiałby rozwiązać z własnego zakresu.

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); 

Jeśli naprawdę chciał dostać fantazyjne z tej opcji, można wdrożyć niestandardowe IContainer który może wykryć jakim kontekście to i postanawia rzeczy z odpowiednim zakresem zagnieżdżonego. W ten sposób działa wielozadaniowe wsparcie Autofac. Jest to jednak znacznie bardziej skomplikowane rozwiązanie, więc nie zamierzam tego tutaj pisać. Sprawdź przykładowe źródło Autofac dla obsługi wielu programów.

Opcja: Można użyć „najniższego wspólnego mianownika” rodzaj rejestracji jak InstancePerDependency lub InstancePerLifetimeScope i pominąć pojęcie mające różną żywotność dla różnych aplikacji.

zauważyć, że właśnie teraz, technicznie, wewnętrznie, nie ma różnicy między tym, co InstancePerHttpRequest i InstancePerWebApiRequest zrobić. Obie sprowadzają się do dokładnie tego samego i są skutecznie wymienne. (Nie mogę obiecać, że zawsze będzie tak na zawsze, ale nie wiem, dlaczego musiałaby się zmienić.)

+0

Awesome! Dziękuję za dokładną odpowiedź, to bardzo pomaga. – chriskopec

+0

myślę, że byłoby to przydatne. jednym z przykładów jest użycie EF frameworku, ponieważ akcja webowa dbcontext, jeśli wywołuje klasę, która potrzebuje dostępu do bazy danych z nowym wątkiem, jest szansa, że ​​jest to tylko wystąpienie requestttttt, spowoduje wyjątek, więc trzeba mieć elastyczność, aby mieć InstancePerLifetimeScope. prawie lepiej po prostu mieć InstancePerLifetimeScope. – koo9

Powiązane problemy