DI 容器和具体值/配置数据

DI containers and concrete values / configuration data

我已经阅读了一些有关 DI 和为您管理 DI 的 DI 容器的内容。

基本上,您创建具有依赖性的 类,并提供一种使用构造函数或 setter 方法进行注入的方法。然后你告诉你的 DI 容器,你想使用哪个具体 类 将所有东西连接在一起。最后,您调用某种服务定位器,它会为您解决所有依赖关系,并通过一行代码为您提供复杂的对象。

我从未使用过具体的 DI 容器实现,所以我想知道 DI 容器如何处理最低级别的对象。这些对象很可能必须使用具体(编码)值或配置文件的内容进行配置。以此为例:

class FooDao {
    public FooDao(DBConnection db) {...}
}

class ConcreteDBConnection : DBConnection {
    public ConcreteDBConnection(String url, int port, String user, String pw)
    {...}
}

您会告诉您的 DI 容器(使用注释、XML 文件或其他方式)您想要使用 ConcreteDBConnection 对象实例化 FooDao 对象。但是您如何告诉您的 DI 容器您的数据库连接所需的具体值呢?如果需要先计算具体值怎么办(比如加密本地存储的数据库连接信息)?

我知道这是一个很笼统的问题,但是我读到的关于 DI 容器的文章也很笼统,这一点让我很困惑。一个任意流行的 DI 框架如何做到这一点的简短解释就足以回答我的问题。

如果你问的是如何使用流行的 DI 容器,有很多关于使用 Castle Windsor 的文章(例如 http://ardalis.com/getting-started-with-castle-windsor),当你尝试其他 DI 框架时,这些概念会很熟悉。温莎城堡确实不错 -- 这是一个很好的起点。

如果您问的是 DI 容器 是如何工作的 -- 这是一个较长的讨论,但基础知识是: 1. 您使用您的框架创建了某种容器。通常像 var container = new Container(); 一样简单 1. 在容器中注册接口 ("service") 到具体 classes 的映射。一些框架有一些魔法可以为你做很多这样的事情,比如最常见的需求:如果你有一个接口 IFoo 并且只有一个分辨率,class Foo,那么它可以自动为你注册(iirc, Autofac 会这样做吗?) 2. 您要求您的容器解析接口——它映射回 classes。在解析期间,您的容器可以检查提供的具体 classes 的构造函数,并尝试根据它们的类型解析参数;同样,它可以根据类型和已知注册来设置属性。