依赖注入 - 正确的注入位置
看看这个关于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);
}
}
当我的应用程序启动时,我显然无法创建此实例。那么我该在哪里注入repo呢?
多谢!
Looking at this answer on SO, I am a bit confused by the following "principle":
Apply the Hollywood Principle
The Hollywood Principle in DI terms says: Don't call the DI Container, it'll call you.
Never directly ask for a dependency by calling a container from within
your code. Ask for it implicitly by using Constructor Injection.
But what if I have a repository class in my DAL, and I want to supply this instance to an object which is created when a TCP/IP client connects? At what place should I make the injection?
Right now, I have something like:
// 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);
}
}
I obviously cannot create this instance when my app is started. So where do I inject the repo?
Thanks a lot!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您应该努力只调用
IoC.GetInstance()
一次。由于您无法在启动时创建 Worker,因此您应该创建一个 WorkerFactory 并让 DI 容器将依赖项注入其中:
You should strive to only call
IoC.GetInstance()
once.Since you cannot create the Worker at startup, you should instead create a WorkerFactory and have the DI container inject the dependency into that:
将
IClientMessagesRepo
移至您的构造函数参数:当然,现在这只会稍微移动问题,直到创建工作线程。当然,在某些时候调用 IoC 容器是必要的。但在这些情况下,我宁愿在参数中传递容器,而不是从静态属性访问它。或者使用某种工厂。
Move
IClientMessagesRepo
to your constructor arguments:Now of course this only moves the problem a bit, to the point where the worker is created. Of course at some point calls into the IoC container are necessary. But in those cases I'd rather pass in the container in a parameter than access it from a static property. Or use some kind of factory.
在您的参数中添加 IClientMessagesRepo,然后让 IoC 为您填充:
显然,您的构造函数应该做的不仅仅是创建几个局部变量,但您明白了。
Have
IClientMessagesRepo
in your arguments, and let the IoC fill that for you:Obviously, your constructor should do a little more than just create a couple local variables, but you get the idea.
据我了解,您的 IOC 容器中有存储库,但没有 IClient。假设您在创建工作类时有权访问 IOC 容器,并且假设您正在使用 StructureMap,您可以编写:
这样您就可以告诉 StructureMap 使用特定的 IClient 实例,但从存储库获取其他依赖项。
注意:自从我上次使用 StructureMap 以来已经有一段时间了,所以也许代码不是 100% 正确,但是概念是存在的,您可以在创建组件时提供具体的依赖项。
As I understand you have the repository in your IOC container, but not the IClient. Assuming that you have access to the IOC container at the time you create your worker class, and assuming that you are using StructureMap you can write:
That way you tell StructureMap to use a specific IClient instance, but obtain the other dependencies from the repository.
note: It is some time since I last used StructureMap, so perhaps the code is not 100% correct, but the concept is there, you can provide a concrete dependency when creating a component.