What is the proper way to create objects which require parameters using autofac?

。_饼干妹妹 提交于 2020-01-23 17:42:05

问题


I think I get most things about dependency inversion and using an IoC container, but one thing still does not appear clear to me. How do I use autofac to automate the following factory:

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

elsewhere...

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

Basically, I need thousands of widgets to be created and I'm not sure of the best way of doing so. How would I create the widget factory using autofac and how would I use that in Method, bearing in mind that Method does not contain a reference to the IContainer?


回答1:


The way to fix this problem is the following:

Change WidgetFactory to define a delegate for creating widgets:

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

In your autofac module, wire up the factory using the RegisterGeneratedFactory method. This will automatically create your factory for you:

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>();
    }
}

Inject the factory into 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:


There are basically two ways to handle parameters:

  • At registration time - you can provide them in lambda registrations (Register(c => T)) or you can append parameters to reflection-based (RegisterType<T>) registrations.
  • At resolve time - you can either append parameters to Resolve<T>() calls or you can use delegate factories or Func<T> dependencies to dynamically create a factory method that can be used by your component.

There is robust documentation on all of these options with examples over at the Autofac documentation site:

  • Parameters at registration time
  • Parameters at resolve time



回答3:


You would inject dependencies into your factory with an IoC container using constructor or property injection, not args into a method. If you needed to inject specific values as parameters into your service's constructor, you could set that up during registration similar to the below code.

Here, I'm getting a XML file path from my web.config and passing that value into my repository's constructor:

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

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


来源:https://stackoverflow.com/questions/24876393/what-is-the-proper-way-to-create-objects-which-require-parameters-using-autofac

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!