Autofac в веб-приложениях, где я должен хранить контейнер для легкого доступа? - PullRequest
14 голосов
/ 14 марта 2009

Я все еще довольно новичок в использовании Autofac, и одна вещь, которую мне не хватает в документации и примерах, - это то, как упростить доступ к сконфигурированному контейнеру из разных мест в веб-приложении.

Я знаю, что могу использовать фабрику контроллеров Autofac для автоматического разрешения инжекционных зависимостей конструктора для контроллеров, но как насчет других вещей, которые вам могут понадобиться для решения, которые еще не внедрены.

Есть ли очевидная закономерность, о которой я не знаю?

Спасибо!

Ответы [ 5 ]

32 голосов
/ 20 июля 2009

«Способ» Autofac должен иметь параметр конструктора IContext. Autofac внедрит объект, который можно использовать для разрешения типов.

Контекст обычно является контейнером за сценой, IContainer реализует интерфейс IContext, хотя IContext ограничен только выполнением разрешений.

Я знаю, что контейнер не должен быть «чрезмерно использован», но у меня есть, как OP, классы, которые требуют разрешения типов, которые не известны заранее (и, следовательно, не могут использоваться в качестве параметров конструктора). Я считаю полезным в этих случаях думать о контейнере как о еще одном сервисе, который можно использовать для разрешения других сервисов, и внедрять его, как любой другой сервис.

Если вы чувствуете, что использование IContext связывает вас с Autofac, и вам необходимо абстрагироваться от этого с помощью собственного интерфейса, это всего лишь вопрос регистрации класса-оболочки IContext в вашем контейнере.

Обновление: в Autofac 2, IContext называется IComponentContext.

12 голосов
/ 14 марта 2009

Прежде всего, старайтесь не злоупотреблять контейнером IoC. Он отлично подходит для «подключения» контроллеров, представлений и служб, но объекты, которые необходимо создавать во время выполнения, должны создаваться объектами фабрики, а не контейнером. В противном случае вы получите Container.Resolve для всех вызовов вашего кода, привязав его к вашему контейнеру. Эти дополнительные зависимости побеждают цель использования IoC. В большинстве случаев я могу получить разрешение только одной или двумя зависимостями на верхнем уровне моего приложения. Контейнер IoC затем рекурсивно разрешит большинство зависимостей.

Когда мне нужен контейнер в другом месте моей программы, я часто использую трюк.

public class Container : IContainer
{
    readonly IWindsorContainer container;

    public Container()
    {
        // Initialize container
        container = new WindsorContainer(new XmlInterpreter(new FileResource("castle.xml")));

        // Register yourself
        container.Kernel.AddComponentInstance<IContainer>(this);
    }

    public T Resolve<T>()
    {
        return container.Resolve<T>();
    }
}

Я заключаю контейнер в класс Container следующим образом. Он добавляет себя в упакованный контейнер в конструкторе. Теперь классам, которым нужен контейнер, может быть добавлен IContainer. (пример для Castle Windsor, но, вероятно, его можно адаптировать для AutoFac)

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

Наличие контейнера IOC по всему миру не является наилучшей практикой. Даже прохождение контейнера не рекомендуется .

Если внедрение зависимостей не может быть использовано (вам нужно создать \ запросить объекты после создания компонента), тогда вы можете:

  1. Использовать фабрики с ручным кодированием (фабрика вводится в компонент, а компонент использует фабрику для создания других объектов)
  2. Использование Autofac делегатских фабрик или новых автоматически генерируемых фабрик в Autofac 2 .
6 голосов
/ 02 августа 2009

Ответ Питера Лиллевольда выше верен - вы можете получить доступ к контейнеру из любого компонента, взяв зависимость от интерфейса IContext.

Если вам действительно действительно нужна ссылка на контейнер, см. Autofac.Integration.Web.IContainerProviderAccessor.

1 голос
/ 14 марта 2009

Обычный способ сделать это - сохранить контейнер в статической переменной в вашем классе приложения Global.

...