看看这个answer on SO,我对以下“原则”感到困惑:
应用好莱坞原则
DI中的好莱坞原则说:不要打电话给DI容器,它会打电话给你。
永远不要通过从内部调用容器来直接询问依赖关系 你的代码。使用构造函数注入隐式请求它。
但是,如果我的DAL中有一个存储库类,并且我想将此实例提供给TCP / IP客户端连接时创建的对象,该怎么办?我应该在什么地方进行注射?
现在,我有类似的东西:
// gets created when a new TCP/IP client is connected
class Worker
{
private readonly IClient client;
public Worker(IClient client)
{
// get the repository
var repo = IoC.GetInstance<IClientMessagesRepo>();
// create an object which will parse messages
var parser = new MessageParser(client);
// create an object which will save them to repo
var logger = new MessageLogger(parser, repo);
}
}
我的应用程序启动时显然无法创建此实例。那么我在哪里注入回购?
非常感谢!
答案 0 :(得分:1)
您应该努力只拨打IoC.GetInstance()
一次。
由于您无法在启动时创建Worker,您应该创建一个WorkerFactory并让DI容器将依赖项注入其中:
public class WorkerFactory
{
private readonly IClientMessagesRepo clientMessagesRepo;
public WorkerFactory(IClientMessagesRepo clientMessagesRepo)
{
this.clientMessagesRepo = clientMessagesRepo;
}
public Worker Create(IClient client)
{
return new Worker(client, clientMessagesRepo);
}
}
答案 1 :(得分:0)
将IClientMessagesRepo
移动到构造函数参数:
public Worker(IClient client,IClientMessagesRepo clientMessagesRepo)
现在当然这只会将问题稍微移动到创建工作者的程度。当然,在某些时候需要调用IoC容器。但在这些情况下,我宁愿在参数中传入容器而不是从静态属性访问容器。或者使用某种工厂。
答案 2 :(得分:0)
在论证中加IClientMessagesRepo
,让IoC为你填写:
public Worker(IClient client, IClientMessagesRepo repo)
{
[...]
}
显然,你的构造函数应该做的不仅仅是创建一些局部变量,但是你明白了。
答案 3 :(得分:0)
据我所知,您在IOC容器中有存储库,但不是IClient。假设您在创建工作类时可以访问IOC容器,并假设您正在使用StructureMap,您可以写:
IClient concreteClient = ...;
worker = container.Using<IClient>(concreteClient).GetInstance<Worker>();
通过这种方式,您可以告诉StructureMap使用特定的IClient实例,但是从存储库中获取其他依赖项。
注意:自从我上次使用StructureMap以来已经有一段时间了,所以代码可能不是100%正确,但是概念就在那里,你可以在创建组件时提供具体的依赖。