依赖注入 - 正确的注入位置

发布于 2024-11-25 23:19:33 字数 966 浏览 1 评论 0原文

看看这个关于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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一身仙ぐ女味 2024-12-02 23:19:33

您应该努力只调用 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);
    }
}

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:

public class WorkerFactory
{
    private readonly IClientMessagesRepo clientMessagesRepo;
    public WorkerFactory(IClientMessagesRepo clientMessagesRepo)
    {
        this.clientMessagesRepo = clientMessagesRepo;
    }

    public Worker Create(IClient client)
    {
        return new Worker(client, clientMessagesRepo);
    }
}
天暗了我发光 2024-12-02 23:19:33

IClientMessagesRepo 移至您的构造函数参数:

public Worker(IClient client,IClientMessagesRepo clientMessagesRepo)

当然,现在这只会稍微移动问题,直到创建工作线程。当然,在某些时候调用 IoC 容器是必要的。但在这些情况下,我宁愿在参数中传递容器,而不是从静态属性访问它。或者使用某种工厂。

Move IClientMessagesRepo to your constructor arguments:

public Worker(IClient client,IClientMessagesRepo clientMessagesRepo)

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.

陌伤ぢ 2024-12-02 23:19:33

在您的参数中添加 IClientMessagesRepo,然后让 IoC 为您填充:

public Worker(IClient client, IClientMessagesRepo repo)    
{
    [...]
}

显然,您的构造函数应该做的不仅仅是创建几个局部变量,但您明白了。

Have IClientMessagesRepo in your arguments, and let the IoC fill that for you:

public Worker(IClient client, IClientMessagesRepo repo)    
{
    [...]
}

Obviously, your constructor should do a little more than just create a couple local variables, but you get the idea.

各自安好 2024-12-02 23:19:33

据我了解,您的 IOC 容器中有存储库,但没有 IClient。假设您在创建工作类时有权访问 IOC 容器,并且假设您正在使用 StructureMap,您可以编写:

IClient concreteClient = ...;
worker = container.Using<IClient>(concreteClient).GetInstance<Worker>();

这样您就可以告诉 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:

IClient concreteClient = ...;
worker = container.Using<IClient>(concreteClient).GetInstance<Worker>();

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文