用 AutoFac 替换工厂 [英] Replace factory with AutoFac

查看:28
本文介绍了用 AutoFac 替换工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我习惯于创建我自己的工厂,如图所示(这是为了说明而简化的):

I'm accustomed to creating my own factories as shown (this is simplified for illustration):

public class ElementFactory
{
    public IElement Create(IHtml dom)
    {
        switch (dom.ElementType)
        {
            case "table":
                return new TableElement(dom);
            case "div":
                return new DivElement(dom);
            case "span":
                return new SpanElement(dom);
        }
        return new PassthroughElement(dom);
    }
}

我终于开始在我当前的项目中使用 IoC 容器 (AutoFac),我想知道是否有一些神奇的方法可以使用 AutoFac 优雅地实现同样的事情?

I'm finally getting around to using an IoC container (AutoFac) in my current project, and I'm wondering is there some magic way of achieving the same thing elegantly with AutoFac?

推荐答案

简短回答:是的.

更长的答案:首先,在类 Foo 注册为 IFoo 的实现的简单情况下,Func 类型的构造函数参数或属性将由 Autofac 自动解析,无需额外需要接线.Autofac 将注入一个委托,该委托在调用时基本上执行 container.Resolve().

Longer answer: First, in simple cases where a class Foo is registered as the implementation for IFoo, constructor parameters or properties of type Func<IFoo> will be resolved automatically by Autofac, with no additional wiring needed. Autofac will inject a delegate that basically executes container.Resolve<IFoo>() when invoked.

在像您这样的更复杂的情况下,返回的确切结石基于输入参数,您可以执行以下两项操作之一.首先,您可以注册一个工厂方法作为其返回值以提供参数化的解析:

In more complex cases like yours, where the exact concretion returned is based on input parameters, you can do one of two things. First, you can register a factory method as its return value to provide a parameterized resolution:

builder.Register<IElement>((c, p) => {
    var dom= p.Named<IHtml>("dom");
    switch (dom.ElementType)
    {
        case "table":
            return new TableElement(dom);
        case "div":
            return new DivElement(dom);
        case "span":
            return new SpanElement(dom);
    }
    return new PassthroughElement(dom);
  });

//usage
container.Resolve<IElement>(new NamedParameter("dom", domInstance))

这不是类型安全的(domInstance 不会被编译器检查以确保它是 IHtml),也不是很干净.相反,另一种解决方案是将工厂方法实际注册为 Func:

This isn't type-safe (domInstance won't be compiler-checked to ensure it's an IHtml), nor very clean. Instead, another solution is to actually register the factory method as a Func:

builder.Register<Func<IHtml, IElement>>(dom =>
{
    switch (dom.ElementType)
    {
        case "table":
            return new TableElement(dom);
        case "div":
            return new DivElement(dom);
        case "span":
            return new SpanElement(dom);
    }
    return new PassthroughElement(dom);
});


public class NeedsAnElementFactory //also registered in AutoFac
{
    protected Func<IHtml,IElement> CreateElement {get; private set;}

    //AutoFac will constructor-inject the Func you registered
    //whenever this class is resolved.
    public NeedsAnElementFactory(Func<IHtml,IElement> elementFactory)
    {
        CreateElement = elementFactory;
    }  

    public void MethodUsingElementFactory()
    {
        IHtml domInstance = GetTheDOM();

        var element = CreateElement(domInstance);

        //the next line won't compile;
        //the factory method is strongly typed to IHtml
        var element2 = CreateElement("foo");
    }
}

如果您想将代码保留在 ElementFactory 中而不是将其放入 Autofac 模块中,您可以将工厂方法设为静态并注册(这在您的情况下特别有效,因为您的工厂方法被简单地设为静态):

If you wanted to keep the code in ElementFactory instead of putting it in the Autofac module, you could make the factory method static and register that (this works especially well in your case because your factory method is trivially made static):

public class ElementFactory
{
    public static IElement Create(IHtml dom)
    {
        switch (dom.ElementType)
        {
            case "table":
                return new TableElement(dom);
            case "div":
                return new DivElement(dom);
            case "span":
                return new SpanElement(dom);
        }
        return new PassthroughElement(dom);
    }
}

...

builder.Register<Func<IHtml, IElement>>(ElementFactory.Create);

这篇关于用 AutoFac 替换工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆