11

我有一个自定义 HTTP 模块。我想使用我的 IoC 框架注入记录器,这样我就可以在模块中记录错误。但是,我当然没有构造函数,所以不能将它注入其中。解决这个问题的最佳方法是什么?

如果您需要特定的 IoC 容器 - 我目前正在使用 Windsor,但可能很快会转向 AutoFac。

谢谢

4

4 回答 4

10

我第一次在 Spring.NET 中看到对 HttpModules 的依赖注入(虽然没有宣传这个框架)。这个想法是你有特殊的 HttpModule,它将依赖项注入到其他应用程序级 HttpModule-s。

不幸的是,当前版本的Autofac.Integration.Web不支持这一点,但您可以自己轻松地做到这一点:

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 应该在 web.config 中的其他 HttpModule-s 之前注册:

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

我相信你可以在温莎做类似的事情。不同之处在于您如何从HttpModuleInjectionModule访问根容器。

于 2009-11-09T08:42:56.817 回答
5

我刚刚在我的博客上回答了这个问题

另请参阅http://lozanotek.com/blog/archive/2009/08/19/Autowire_IHttpModules_with_IoC.aspx

于 2009-11-01T19:59:18.670 回答
3

您可以通过 Init 方法传递给您的 HttpApplication 上下文传入所需的依赖项...

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

    public void Dispose()
    {
    }
}
于 2009-11-03T08:25:54.687 回答
1

我对 andrey-tsykunov 的回答很好奇,但没有代表对此发表评论。

我正在努力适应 IoC 和 DI,所以我可能会遗漏一些东西,但是从 MyModule 中使用 IContainerProviderAccessor 会比创建另一个模块更简单吗?

例如:

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; }
}
于 2010-09-10T16:28:33.617 回答