Я думаю, что я получаю большую часть информации об инверсии зависимостей и использовании контейнера 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?
Способ устранения этой проблемы заключается в следующем:
Измените 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
}
}
Существует два способа обработки параметров:
Register(c => T)
), или вы можете добавить параметры к регистрации на основе отражения (RegisterType<T>
).Resolve<T>()
либо использовать фабрики делегатов или зависимости Func<T>
для динамического создания фабричного метода, который может использоваться вашим компонентом.Во всех этих вариантах есть надежная документация с примерами на сайте документации Autofac:
Вы должны вводить зависимости на свой завод с контейнером 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();