使用autofac创建需要参数的对象的正确方法是什么?

时间:2014-07-21 23:14:40

标签: c# autofac

我认为我得到了关于依赖倒置和使用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创建窗口小部件工厂?如何在Method中使用它,请记住Method不包含对IContainer的引用?

3 个答案:

答案 0 :(得分:7)

解决此问题的方法如下:

更改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
    }
}

答案 1 :(得分:2)

基本上有两种处理参数的方法:

  • 在注册时 - 您可以在lambda注册(Register(c => T))中提供它们,或者您可以将参数附加到基于反射的(RegisterType<T>)注册。
  • 在解决时间 - 您可以将参数附加到Resolve<T>()调用,也可以使用委托工厂或Func<T>依赖项动态创建可供组件使用的工厂方法。

有关所有这些选项的强大文档,以及Autofac文档站点上的示例:

答案 2 :(得分:0)

您可以使用构造函数或属性注入向IoC容器注入依赖项,而不是args到方法中。如果您需要将特定值作为参数注入服务的构造函数,则可以在注册期间将其设置为类似于以下代码。

在这里,我从web.config获取XML文件路径并将该值传递到我的存储库的构造函数中:

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

builder.Register(c => new XmlAdvertisementRepository(new XmlContext(xmlFileName)))
    .AsImplementedInterfaces()
    .InstancePerHttpRequest();