问题描述
我习惯了,如图创造我自己的工厂(这是简化了说明):
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键<的IFoo>
将自动Autofac解决,且无需额外布线。 Autofac将注入的委托,基本上执行 container.Resolve<的IFoo方式>()调用时
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.
在更复杂像你这样的,其中返回的确切结石是基于输入参数的情况下,你可以做两件事情之一。 IElement>((
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替换厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!