Как правильно создавать объекты, для которых требуются параметры, используя автофакт?

1

Я думаю, что я получаю большую часть информации об инверсии зависимостей и использовании контейнера IoC, но мне все еще не ясно. Как использовать autofac для автоматизации следующей фабрики:

public class WidgetFactory
{
    public static IWidget Create(int foo, double bar)
    {
        return new Widget(foo, bar);
    }
}

public class Widget
{
    private readonly int foo;
    private readonly double bar;

    public Widget(int foo, double bar)
    {
        this.foo = foo;
        this.bar = bar;
    }
}

в другом месте...

public class FoobarUser
{
    public void Method()
    {
        var widget = WidgetFactory.Create(3, 4.863);
        // Do something with my widget
        // Possibly add it to a widget collection
    }
}

В принципе, мне нужно создать тысячи виджетов, и я не уверен в этом. Как создать фабрику виджета с помощью autofac и как я буду использовать ее в методе, имея в виду, что метод не содержит ссылки на IContainer?

Теги:
autofac

3 ответа

5
Лучший ответ

Способ устранения этой проблемы заключается в следующем:

Измените WidgetFactory, чтобы определить делегата для создания виджетов:

public class WidgetFactory
{
    public delegate IWidget Create(int firstParam, double secondParam);
}

В вашем модуле autofac подключите фабрику, используя метод RegisterGeneratedFactory. Это автоматически создаст ваш завод для вас:

public class TestClassModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        base.Load(builder);

        builder.RegisterType<Widget>().As<IWidget>();
        builder.RegisterGeneratedFactory<WidgetFactory.Create>(new TypedService(typeof(IWidget)));

        builder.RegisterType<FoobarUser>();
    }
}

Внесите завод в FoobarUser:

public class FoobarUser
{

    private readonly WidgetFactory.Create factory;

    public FoobarUser(WidgetFactory.Create factory)
    {
        this.factory = factory;
    }

    public void Method()
    {
        var widget = this.factory(3, 4.836);
        // Do something with my widget
        // Possibly add it to a widget collection
    }
}
2

Существует два способа обработки параметров:

  • Во время регистрации вы можете предоставить их в лямбда-регистрациях (Register(c => T)), или вы можете добавить параметры к регистрации на основе отражения (RegisterType<T>).
  • Во время разрешения вы можете либо добавить параметры к вызовам Resolve<T>() либо использовать фабрики делегатов или зависимости Func<T> для динамического создания фабричного метода, который может использоваться вашим компонентом.

Во всех этих вариантах есть надежная документация с примерами на сайте документации Autofac:

  • 0
    Это указало мне правильное направление, спасибо.
0

Вы должны вводить зависимости на свой завод с контейнером IoC, используя конструктор или вложение свойств, а не аргументы в метод. Если вам нужно было ввести определенные значения в качестве параметров в свой конструктор службы, вы можете установить это во время регистрации, аналогично приведенному ниже коду.

Здесь я получаю путь к файлу XML из моего web.config и передаю это значение в свой конструктор репозитория:

var builder = new ContainerBuilder();
var xmlFileName = HttpContext.Current.Server.MapPath(
    ConfigurationManager.AppSettings["xmlData"]);

builder.Register(c => new XmlAdvertisementRepository(new XmlContext(xmlFileName)))
    .AsImplementedInterfaces()
    .InstancePerHttpRequest();
  • 0
    Проблема в том, что вы не знаете во время компиляции, какими будут значения - они динамически генерируются во время выполнения, и приложение может использовать тысячи уникальных экземпляров одновременно.
  • 0
    Если они не являются зависимостями (в большинстве случаев это сервисы), вы бы их не внедрили. Заводской метод, который вы создали, кажется уместным.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню