11

Tengo un módulo HTTP personalizado. Me gustaría inyectar el registrador usando mi framework IoC, así puedo registrar errores en el módulo. Sin embargo, por supuesto no tengo un constructor, así que no puedo inyectarlo en eso. ¿Cuál es la mejor manera de hacerlo?IoC Dependency injection into Custom HTTP Module: ¿cómo? (ASP.NET)

Si necesita el contenedor específico de IoC, actualmente estoy usando Windsor, pero es posible que pronto cambie a AutoFac.

Gracias

+0

Se puede usar un localizador de servicios, echar un vistazo a esta pregunta: [Diferencia entre la inyección de dependencia y el patrón de localización de servicios] (http://stackoverflow.com/questions/1557781/ whats-the-difference-between-the-dependency-injection-and-service-locator-patter) – FinnNk

Respuesta

2

Usted podría pasar en las dependencias necesarias a través del contexto HttpApplication pasado a usted por el método Init ...

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

    public void Dispose() 
    { 
    } 
} 
+2

-1 porque es muy difícil burlarse de las dependencias de esta manera –

+0

@Mauricio Scheffer: Tal vez, pero luego simplemente implemente el módulo como un Humble Executable. Prefiero ese enfoque sobre el uso de inyección estática. La gente piensa que ayuda a la capacidad de prueba, pero realmente lo lastima. –

+1

Humble Executable ciertamente funciona bien en este caso, agregaría esa información a la respuesta. Sin embargo, puedes tener tu pastel y comértelo también, ver mi solución. –

10

primera vez que vi la inyección de dependencia a HttpModules en la primavera. NET (sin anunciar este marco) La idea es que tengas un HttpModule especial que inyecte dependencias a otros HttpModule-s a nivel de aplicación.

Desafortunadamente versión actual de Autofac.Integration.Web no es compatible con este, pero se puede hacer fácilmente que usted mismo:

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 deben estar registrados antes de otra HttpModule-s en 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> 

Estoy seguro de que puedes hacer cosas similares en Windsor. La diferencia estaría en la forma de acceder a su contenedor raíz desde HttpModuleInjectionModule.

+0

esto es bastante limitado, no se puede hacer la inyección del constructor. –

1

Tengo curiosidad por la respuesta de andrey-tsykunov, pero no tengo el representante para comentar al respecto.

Estoy tratando de ponerme cómodo con IoC y DI, por lo que me puede faltar algo, pero ¿no sería más sencillo usar IContainerProviderAccessor desde MyModule, en lugar de crear otro módulo?

Por ejemplo:

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

No está haciendo la inyección de dependencia aquí, está haciendo la ubicación del servicio. –

+3

Parece que tiene ordenado el representante: P –

Cuestiones relacionadas