我正在处理的应用程序依赖 Autofac 作为 DI 容器,而让我决定使用它的原因之一是委托(delegate)工厂功能(参见 here)
这适用于我需要多次重新创建相同元素的所有情况,就像某些报告和相关屏幕的情况一样。一些报告(甚至是相同类型的报告)是同时执行的,但它们仅通过用户定义的参数进行更改,因此(我认为)注入(inject)工厂以创建实例、传递自由参数并将其余的留给申请。
问题在于每个报告都由数量可变的子报告(任务)组成,并且每个任务都实现一个 ITask 接口(interface)。每个报表最多可以使用 50 个不同的任务,每个任务都封装了一个精确的业务操作。我的一个选择是注入(inject)委托(delegate)工厂并在需要时创建它们。
这些任务必须由工厂动态生成,例如:
var myTaskA = _taskFactoryConcreteTaskA();
var myTaskB = _taskFactoryConcreteTaskB();
var myTaskC = _taskFactoryConcreteTaskC();
...
var myTaskZZ = = _taskFactoryConcreteTaskZZ();
需要大量手动连接(委托(delegate)、构造函数、支持字段等),而类似
var myTaskA = _taskFactory.Create<ConcreteTaskA>();
var myTaskB = _taskFactory.Create<ConcreteTaskB>();
var myTaskC = _taskFactory.Create<ConcreteTaskC>();
...
var myTaskZZ = _taskFactory.Create<ConcreteTaskZZ>();
工作量会少得难以置信,特别是如果 _taskFactory 包装容器,如 this other post 所示。 ,但这也基本上意味着我正在使用服务定位器来创建我的任务。
我还有哪些适合解决此问题的其他选择?
(注意:很有可能我完全偏离了正轨,我必须阅读更多有关 DI 的内容,在这种情况下,任何贡献都会更加重要)
最佳答案
由于问题中指出的工厂不接受任何参数,因此使用工厂有Leaky Abstraction 的味道。正如 Nicholas Blumhardt 在他的回答中指出的那样,更好的方法可能是简单地将每个任务注入(inject)消费者。
在这种情况下,由于所有任务都实现相同的接口(interface),而不是注入(inject)多达 50 个不同的 ITask
实例,您可以组合它们:
public class MyConsumer
{
private readonly IEnumerable<ITask> tasks;
public MyConsumer(IEnumerable<ITask> tasks)
{
this.tasks = tasks;
}
public void DoSomething()
{
foreach (var t in this.tasks)
{
// Do something with each t
}
}
}
或者,您可以将 ITasks
序列组合成 Composite ,这实际上是我的首选解决方案:
public CompositeTask : ITask
{
private readonly IEnumerable<ITask> tasks;
public CompositeTask(IEnumerable<ITask> tasks)
{
this.tasks = tasks;
}
// Implement ITask by iterating over this.tasks
}
这将简化消费者并将要执行多个任务的事实转化为实现细节:
public class MyConsumer
{
private readonly ITask task;
public MyConsumer(ITask task)
{
this.task = task;
}
public void DoSomething()
{
// Do something with this.task
}
}
关于c# - 服务定位器比依赖注入(inject)更容易使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8086026/