我有一个名为IProcessor的接口,有多个实现,如ABCProcessor, PQRProcessor。我想利用基于外部参数的特定处理器。如何使用StructureMap实现相同的功能?
我正在寻找相同的命名实例。
您可以使用工厂模式:
public interface IProcessorFactory
{
IProcessor Create(int dropDownValue);
}
public class ProcessorFactory : IProcessorFactory
{
private readonly IContainer _container;
public ProcessorFactory(IContainer container)
{
_container = container;
}
public IProcessor Create()
{
if(//your condition)
return _container.GetInstance<ABCProcessor>();
_container.GetInstance<PQRProcessor>();
}
}
(或者只是注入所需的依赖项而不是容器)然后直接
private readonly IProcessorFactory _processorFactory;
public MvcController(IProcessorFactory processorFactory)
{
_processorFactory = processorFactory;
}
public void Method()
{
var processor = _processorFactory.Create();
}
你的问题的最佳解决方案是通过实现IProcessor
的代理实现,对消费者隐藏存在多种实现的知识和它们之间的选择:
public sealed ProxyProcessor : IProcessor
{
private readonly ABCProcessor abc;
private readonly PQRProcessor pqr;
private readonly IProcessorConfig config;
public ProxyProcessor(ABCProcessor abc, PQRProcessor pqr, IProcessorConfig config) {
this.abc = abc;
this.pqr = pqr;
this.config = config;
}
// Implement IProcessor methods to forward to the CurrentProcessor.
public void Process() => CurrentProcessor.Process();
private IProcessor CurrentProcessor => config.ProcessorType == "ABC" ? abc : pqr;
}
通过这样做,您可以在运行时委托给正确的实现,而消费者仍然忽略您在运行时对此做出决定的事实。现在不是向消费者注射ABCProcessor
或PQRProcessor
,而是向消费者注射ProxyProcessor
。例如,ProxyProcessor
的对象图可能是这样的:
IProcessor processor =
new ProxyProcessor(
abc: new ABCProcessor(),
pqr: new PQRProcessor(),
config: new SqlProcessorConfig("constr"));
请注意,与使用工厂相比,这个解决方案有几个优点,例如:
- 它防止对消费者进行任何更改;消费者对此无动于衷。
- 它防止给消费者带来不必要的复杂性;使用工厂方法,消费者必须处理额外的依赖项。这会使代码和测试变得复杂。
- 导致对象图以延迟的方式构造,从而使对象图的验证变得复杂。
如果你想知道为什么工厂从来都不是正确的抽象,请阅读这篇文章