开发者

IoC Dependency injection into Custom HTTP Module - how? (ASP.NET)

I have a custom HTTP Module. I would like to inject the logger using my IoC framework, so I can log errors in the module. However, of course I don't get a constructor, so can't inject it into that. What's the best way to go about this?

If you need the specific IoC container - I'm currently using Windsor, but may开发者_运维知识库 soon move to AutoFac.

Thanks


First time I saw dependency injection to HttpModules in Spring.NET (not advertising this framework though). The idea is that you have special HttpModule which injects dependencies to other application-level HttpModule-s.

Unfortunatelly current version of Autofac.Integration.Web does not support this, but you can easily do that yourself:

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 should be registered before other HttpModule-s in 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>

I'm sure you can do similar things in Windsor. The difference would be in how you access your root container from HttpModuleInjectionModule.


I just answered this question on my blog.

See also http://lozanotek.com/blog/archive/2009/08/19/Autowire_IHttpModules_with_IoC.aspx


You could pass in the required dependencies via the HttpApplication context passed to you by the Init method...

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

    public void Dispose()
    {
    }
}


I am curious about andrey-tsykunov's answer, but don't have the rep to comment on it.

I am trying to get comfortable with IoC and DI, so I may be missing something, but wouldn't it be simpler to use IContainerProviderAccessor from within MyModule, rather than create another module?

For example:

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; }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜