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

时间:2011-07-25 11:35:24

标签: c# dependency-injection repository ioc-container

看看这个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);
    }
}

我的应用程序启动时显然无法创建此实例。那么我在哪里注入回购?

非常感谢!

4 个答案:

答案 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%正确,但是概念就在那里,你可以在创建组件时提供具体的依赖。