2016-04-14 12 views
8

Aktualnie używam Simple Injector do rozwiązywania zależności w moich projektach Asp.Net Web Api.Rozwiązywanie zależności w interfejsie API ASP.NET Web z prostym wtryskiwaczem i mechanizmem IHttpControllerActivator

Z dokumentacji można skonfigurować go tak:

protected void Application_Start() { 
    // Create the container as usual. 
    var container = new Container(); 
    container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle(); 

    // Register your types, for instance using the scoped lifestyle: 
    container.Register<IUserRepository, SqlUserRepository>(Lifestyle.Scoped); 

    // This is an extension method from the integration package. 
    container.RegisterWebApiControllers(GlobalConfiguration.Configuration); 

    container.Verify(); 

    GlobalConfiguration.Configuration.DependencyResolver = 
     new SimpleInjectorWebApiDependencyResolver(container); 

    // Here your usual Web API configuration stuff. 
} 

Główne punkty są tu zarejestrować kontrolerów api WWW i ustawić resolverowi zwyczaj zależność.

Jednak mam tylko czytać te artykuł z Mark Seemann, w jaki sposób skonfigurować iniekcji zależność w ASP.NET Web API:

z takich wyrobów, I dowiedziałem się, że istnieje lepsza opcja niż implementacja IDependencyResolver w celu rozwiązania zależności Web Api. Ta druga opcja polega na utworzeniu implementacji IHttpControllerActivator, która działa jako adapter w stosunku do kontenera IoC.

Oto implementacja mam zakodowane przy użyciu SimpleInjector:

public class SimpleInjectorControllerActivator : IHttpControllerActivator 
{ 
    private readonly Container _container; 

    public SimpleInjectorControllerActivator(Container container) 
    { 
     _container = container; 
    } 

    public IHttpController Create(HttpRequestMessage request, 
     HttpControllerDescriptor controllerDescriptor, Type controllerType) 
    { 
     request.RegisterForDispose(_container.BeginExecutionContextScope()); 

     return (IHttpController)_container.GetInstance(controllerType); 
    } 
} 

iw sposobie Application_Start, mam wymienić tę linię:

GlobalConfiguration.Configuration.DependencyResolver = 
    new SimpleInjectorWebApiDependencyResolver(container); 

przez tę linię:

GlobalConfiguration.Configuration.Services.Replace(
    typeof(IHttpControllerActivator), 
    new SimpleInjectorControllerActivator(container)); 

Chciałbym wiedzieć, czy wdrożenie IHttpControllerActivator i s ważne, a także czy to podejście jest prawidłowe i będzie działało tak dobrze, jak normalne?

+1

Zamiast publikować zaktualizowaną wersję, zaktualizowałem Twoje pytanie za pomocą uproszczonej wersji SimpleInjectorControllerActivator. – Steven

Odpowiedz

3

Tak, twoje wdrożenie jest ważne.

Należy uważać, aby nie używać zarówno SimpleInjectorWebApiDependencyResolver, jak i SimpleInjectorControllerActivator w tej samej aplikacji. Oba zaczynają od ExecutionContextScope, co może prowadzić do posiadania dwóch zakresów w ramach tego samego żądania internetowego, więc wzajemnie się wykluczają.

Ogólna zaleta korzystania z aktywatora kontrolera przez narzędzie do rozstrzygania zależności polega na tym, że kontrakt rozwiązywania problemów powoduje, że adapter zwraca null, gdy usługa nie może zostać utworzona. Jest to bardzo powszechny problem, na który napotykają programiści, i często powoduje to mylące wyjątek z controller does not have a default constructor. Ten problem nie istnieje podczas korzystania z IHttpControllerActivator, ponieważ kontrakt wymusza zwrócenie wartości lub wygenerowanie wyjątku.

Simple Injector Web projekt integracja API jednak uniemożliwia ten problem z zależnościami rezolwerem, by nigdy nie wracać null (ale rzuca wyjątek zamiast) w przypadku, gdy żądana usługa jest kontroler API (a tym samym pośrednio zerwania umowy ze IDependencyResolver dydaktycznego).

Zaletą korzystania z SimpleInjectorDependencyResolver jest to, że łatwiej jest tworzyć procedury obsługi komunikatów, które działają w zakresie kontekstu wykonywania, ponieważ można wywołać tworzenie tego zakresu, wywołując metodę request.GetDependencyScope().Przy obecnej implementacji zakres zaczyna się od momentu utworzenia kontrolera, po uruchomieniu procedur obsługi. Zmiana tego nie jest trudna, ale wymaga zmiany aktywatora kontrolera i posiadania najbardziej zewnętrznego programu obsługi, który rozpoczyna zakres kontekstu wykonywania (lub ponownie znajduje się w repozytorium zależności, który zarządza zakresem kontekstu wykonywania).

Jednym z argumentów Marka Seemanna jest to, że trudno jest przekazać kontekst, co jest bardzo ważnym punktem, o ile Twój components don't require this context during construction. Ale nie jest to problem, który można napotkać podczas korzystania z Simple Injector, ponieważ istnieje extension method, który pomaga w uzyskaniu dostępu do HttpRequestMessage. Tak więc, chociaż abstrakcja IDependencyResolver nie jest przeznaczona do uzyskiwania informacji kontekstowych, istnieją sposoby uzyskania tej informacji kontekstowej.

W przeszłości zdecydowaliśmy się na adapter z IDependencyResolver, głównie dlatego, że było to powszechną praktyką we wszystkich kontenerach DI. Częściowo żałuję tej decyzji, ale używanie SimpleInjectorDependencyResolver jest obecnie najłatwiejszym sposobem na podłączenie Simple Injector do Web API. Zastanawialiśmy się także nad dodaniem SimpleInjectorControllerActivator, ale nie przyniosło to praktycznej korzyści dla większości użytkowników, a my nadal musielibyśmy udokumentować, kiedy użyć czego. Postanowiliśmy więc trzymać się adaptera zależnego resolver; Adapter dla aktywatora można łatwo utworzyć dla każdego, kto go potrzebuje, jak widać.

Dla ASP.NET Core jednak udaliśmy się w innym kierunku, a jak widać w the documentation, pakiet integracyjny faktycznie zawiera SimpleInjectorControllerActivator po wyjęciu z pudełka. W środowisku ASP.NET Core aktywator kontrolera jest idealnym punktem przechwytywania, a dzięki potokowi podobnemu do OWIN zakres może być łatwo zawinięty wokół żądania. W ASP.NET Core zalecana praktyka polega na użyciu aktywatora kontrolera jako punktu przechwytywania.

+0

Dzięki Steven! Muszę rzucić okiem na core core asp.net, ponieważ zastanawiam się, czy to podejście jest nadal aktualne w podstawowym asp.netu? – Thomas

+0

Czy jest jakaś szansa, aby takie podejście było domyślną integracją z interfejsem webowym za pomocą prostego wtryskiwacza? – Thomas

+0

W tym konkretnym przypadku, jakie są zalety używania 'SimpleInjectorControllerActivator' przez' SimpleInjectorWebApiDependencyResolver', jeśli oba zaczynają 'ExecutionContext'? Jaki rodzaj informacji * kontekst * można uzyskać za pomocą 'ControllerActivator', którego nie można uzyskać za pomocą' DependencyResolver'? –

Powiązane problemy