11

Mam niestandardowy moduł HTTP. Chciałbym wstrzyknąć rejestrator za pomocą mojego środowiska IoC, aby móc rejestrować błędy w module. Jednak oczywiście nie dostaję konstruktora, więc nie mogę go do tego wstrzyknąć. Jaki jest najlepszy sposób na rozwiązanie tego problemu?Wstrzyknięcie zależności IoC do niestandardowego modułu HTTP - jak? (ASP.NET)

Jeśli potrzebujesz konkretnego pojemnika IoC - aktualnie używam Windsora, ale wkrótce mogę przejść do AutoFac.

Dzięki

+0

można użyć lokalizatora usług, przyjrzeć się tej kwestii: [różnica między wstrzykiwania zależności i lokalizatora usług wzór] (http://stackoverflow.com/questions/1557781/ whats-the-difference-between-dependency-injection-and-service-locator-patter) – FinnNk

Odpowiedz

2

Można przejść w zależności wymaganych przez kontekście HttpApplication przekazany do ciebie metodą Init ...

public class MyHttpModule : IHttpModule 
{ 
    public void Init(HttpApplication context) 
    { 
     var dependency = (IDependency)context.Context.Items["dependency"]; 
     // consume dependency... 
    } 

    public void Dispose() 
    { 
    } 
} 
+2

-1, ponieważ bardzo trudno jest wyśmiewać zależności w ten sposób –

+0

@Mauricio Scheffer: Być może, ale po prostu zaimplementuj moduł jako Humble Executable. Preferuję to podejście w stosunku do używania statycznego wtrysku. Ludzie myślą, że to pomaga w testowaniu, ale to naprawdę boli. –

+1

Humble Executable z pewnością dobrze działa w tym przypadku, dodałbym tę informację do odpowiedzi. Jednak możesz mieć swoje ciasto i zjeść je, zobacz moje rozwiązanie. –

10

Pierwszy raz widziałem Dependency Injection do HttpModules na wiosnę. NET (nie reklamując tego systemu). Chodzi o to, że masz specjalny moduł HttpModule, który wstrzykuje zależności do innych HttpModule-ów na poziomie aplikacji.

Niestety obecna wersja Autofac.Integration.Web nie obsługuje to, ale łatwo można zrobić samemu:

public class MyModule : IHttpModule 
{ 
    public void Dispose() 
    {    
    } 

    public void Init(HttpApplication context) 
    { 
     Assert.IsNotNull(MyService); 
    }   

    public IMyService MyService { get; set; } 
} 

public class HttpModuleInjectionModule : IHttpModule 
{ 
    public void Dispose() 
    {    
    } 

    public void Init(HttpApplication context) 
    { 
     var containerProviderAccessor = context as IContainerProviderAccessor; 

     if(containerProviderAccessor == null) 
      throw new InvalidOperationException("HttpApplication should implement IContainerProviderAccessor"); 

     var rootContainer = containerProviderAccessor.ContainerProvider.ApplicationContainer; 

     foreach (string moduleName in context.Modules.AllKeys) 
      rootContainer.InjectProperties(context.Modules[moduleName]); 
    } 
} 

public class Global : HttpApplication, IContainerProviderAccessor 
{ 
    static IContainerProvider _containerProvider; 

    protected void Application_Start(object sender, EventArgs e) 
    { 
    var builder = new ContainerBuilder(); 
    builder.Register<MyService>().As<IMyService>(); 
    _containerProvider = new ContainerProvider(builder.Build()); 
    } 

    public IContainerProvider ContainerProvider 
    { 
    get { return _containerProvider; } 
    } 
} 

HttpModuleInjectionModule powinna zostać zarejestrowana zanim inny HttpModule-s w pliku web.config:

<httpModules> 
    <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> 
    <add name="HttpModuleInjection" type="WebTest.HttpModuleInjectionModule, WebTest"/> 
    <add name="ContainerDisposal" type="Autofac.Integration.Web.ContainerDisposalModule, Autofac.Integration.Web"/> 
    <add name="PropertyInjection" type="Autofac.Integration.Web.PropertyInjectionModule, Autofac.Integration.Web"/> 
    <add name="MyModule" type="WebTest.MyModule, WebTest"/> 
    </httpModules> 

Jestem pewien, że możesz robić podobne rzeczy w Windsor. Różnica polega na tym, w jaki sposób uzyskujesz dostęp do kontenera głównego z HttpModuleInjectionModule.

+0

Jest to dość ograniczone, nie można wykonać zastrzyku konstruktora. –

1

Jestem ciekawy odpowiedzi andrey-tsogonov, ale nie mam przedstawiciela, który mógłby go skomentować.

Próbuję uzyskać wygodę z IoC i DI, więc być może czegoś mi brakuje, ale czy nie byłoby prostsze korzystanie z IContainerProviderAccessor z MyModule zamiast tworzenia kolejnego modułu?

Na przykład:

public class MyModule : IHttpModule 
{ 
    public void Dispose() 
    {    
    } 

    public void Init(HttpApplication context) 
    { 
     Assert.IsNotNull(MyService); 

     var containerProviderAccessor = context as IContainerProviderAccessor; 

     if (accessor != null) 
     { 
      IContainer container = containerProviderAccessor.ContainerProvider.ApplicationContainer; 
      MyService = container.Resolve<IMyService>(); 
     } 
    } 

    private IMyService MyService { get; set; } 
} 
+4

Nie robisz tu zastrzyku zależności, robisz lokalizację usługi. –

+3

Wygląda na to, że masz posortowaną rzecz: P –

Powiązane problemy