11

我有一个自定义HTTP模块。我想用我的IoC框架注入记录器,这样我就可以在模块中记录错误。然而,当然我没有得到一个构造函数,所以不能将它注入到构造函数中。什么是最好的方式去做这件事?IoC依赖注入到自定义HTTP模块 - 如何? (ASP.NET)

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

谢谢

+0

你可以使用一个服务定位器,看看这个问题:([依赖注入和服务定位器模式之间的不同] http://stackoverflow.com/questions/1557781/ what-the-the-difference-between-dependency-injection-and-service-locator-patter) – FinnNk 2009-11-01 16:00:21

回答

2

见你可以在需要的依赖通过由init方法传递给你的HttpApplication的情况下通过......

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

    public void Dispose() 
    { 
    } 
} 
+2

-1,因为很难用这种方式嘲笑依赖关系 – 2009-11-03 15:48:42

+0

@Mauricio Scheffer:也许,但随后只是将模块实现为卑微的可执行文件。我更喜欢使用静态注入的方法。人们认为它有助于可测性,但它确实伤害了它。 – 2009-11-03 16:22:12

+1

在这种情况下,Humble Executable当然可以很好地工作,我会将该信息添加到答案中。但是,你可以吃你的蛋糕,也可以吃它,看看我的解决方案。 – 2009-11-03 16:41:34

10

第一次见到依赖注入的HttpModules在春季。 NET(不是通过这个框架)。这个想法是你有特殊的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应先于其他的HttpModule-S在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> 

我相信你可以在温莎做类似的事情。区别在于如何从HttpModuleInjectionModule访问根容器。

+0

这是相当有限的,不能做构造函数注入。 – 2010-10-07 20:38:18

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; } 
} 
+4

您在这里没有执行依赖注入,您正在执行服务位置。 – 2010-10-07 20:40:02

+3

看起来像你有rep事物排序:P – 2014-09-20 07:47:08