Внедрение зависимостей IoC в пользовательский модуль HTTP - как? (ASP.NET) - PullRequest
11 голосов
/ 01 ноября 2009

У меня есть собственный модуль HTTP. Я хотел бы внедрить регистратор, используя мою среду IoC, чтобы я мог регистрировать ошибки в модуле. Однако, конечно, я не получаю конструктор, поэтому не могу вставить его в это. Какой лучший способ сделать это?

Если вам нужен конкретный контейнер IoC - я сейчас использую Windsor, но скоро могу перейти на AutoFac.

Спасибо

Ответы [ 4 ]

10 голосов
/ 09 ноября 2009

Впервые я увидел внедрение зависимостей в HttpModules в Spring.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 .

5 голосов
/ 01 ноября 2009
2 голосов
/ 03 ноября 2009

Вы можете передать необходимые зависимости через контекст HttpApplication, переданный вам методом Init ...

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

    public void Dispose()
    {
    }
}
1 голос
/ 10 сентября 2010

Мне любопытно ответить Андрея Цыкунова, но у меня нет представителя, чтобы комментировать.

Я пытаюсь освоиться с IoC и DI, поэтому я могу что-то упустить, но не проще ли использовать IContainerProviderAccessor из MyModule, а не создавать другой модуль?

Например:

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