11

J'ai un module HTTP personnalisé. Je voudrais injecter l'enregistreur en utilisant mon framework IoC, afin que je puisse enregistrer les erreurs dans le module. Cependant, bien sûr, je n'ai pas de constructeur, donc je ne peux pas l'intégrer dans ça. Quelle est la meilleure façon d'y parvenir?Injection de dépendance IoC dans le module HTTP personnalisé - comment? (ASP.NET)

Si vous avez besoin du conteneur IoC spécifique - j'utilise actuellement Windsor, mais je pourrais bientôt passer à AutoFac.

Merci

+0

Vous pouvez utiliser un localisateur de services, jetez un oeil à cette question: [différence entre l'injection de dépendance et le modèle de localisation de service] (http://stackoverflow.com/questions/1557781/ whats-the-difference-between-the-dependency-injection-and-service-locator-patter) – FinnNk

Répondre

2

Vous pouvez passer dans les dépendances requises par le contexte HttpApplication passé à vous par la méthode Init ...

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

    public void Dispose() 
    { 
    } 
} 
+2

-1 parce qu'il est très difficile de simuler les dépendances de cette façon –

+0

@Mauricio Scheffer: Peut-être, mais il suffit d'implémenter le module en tant que Humble Executable. Je préfère cette approche à l'utilisation de l'injection statique. Les gens pensent que cela aide la testabilité, mais ça fait vraiment mal. –

+1

Humble Executable fonctionne bien dans ce cas, je voudrais ajouter cette information à la réponse. Cependant, vous pouvez avoir votre gâteau et le manger aussi, voir ma solution. –

10

première fois que je voyais l'injection de dépendance à HttpModules au printemps. NET (ne pas annoncer ce cadre si). L'idée est que vous avez HttpModule spécial qui injecte des dépendances à d'autres HttpModule-s au niveau de l'application.

Unfortunatelly version actuelle de Autofac.Integration.Web ne supporte pas, mais vous pouvez facilement faire vous-même:

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 doit être enregistré avant les autres HttpModule-s dans 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> 

Je suis sûr que vous pouvez faire des choses semblables à Windsor. La différence réside dans la façon dont vous accédez à votre conteneur racine à partir de HttpModuleInjectionModule.

+0

c'est assez limité, ne peut pas faire l'injection de constructeur. –

1

Je suis curieux à propos de la réponse d'andrey-tsykunov, mais je n'ai pas le représentant pour le commenter. J'essaie de me familiariser avec IoC et DI, donc il me manque peut-être quelque chose, mais ne serait-il pas plus simple d'utiliser IContainerProviderAccessor dans MyModule, plutôt que de créer un autre module?

Par exemple:

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

Vous n'effectuez pas d'injection de dépendance ici, vous effectuez un emplacement de service. –

+3

On dirait que vous avez trié le rep: P –