26

我正在使用 Unity IOC 容器,我只是想知道访问多个类的容器的最佳方式是什么。

每个类都应该有一个 IUnityContainer 成员,然后通过构造函数传入容器吗?是否应该有一个带有 IOC 容器的单例类?

asp.net开发怎么样?

有人可以指导我正确的方向吗?谢谢。

4

6 回答 6

22

恕我直言,不建议将整个容器注入一个类或拥有一个应用程序范围的静态 IoC 服务定位器。

您希望能够从一个类的构造函数(我们称之为 Foo)中看到它使用什么样的服务/对象来完成工作。这提高了清晰度、可测试性和可调试性。

假设 Foo 只需要电子邮件服务,但我传入整个容器以及电子邮件服务从容器中解析的代码中的某处。在这种情况下,将很难遵循。相反,最好直接注入电子邮件服务以更清楚地说明 Foo 的依赖关系。

如果 Foo 需要创建电子邮件服务的多个实例,最好创建和注入一个 EmailServiceFactory(通过 IoC 容器),它将即时创建所需的实例。

在后一种情况下,Foo 的依赖关系仍然尽可能具体地表示 - 只有那些 EmailServiceFactory 可以创建的依赖关系。如果我注入了整个容器,就不清楚它提供的服务是 Foo 的确切依赖项。

现在,如果我以后想要提供电子邮件服务的不同实例,我将在 EmailServiceFactory 中将其换掉。如果它创建的所有服务都需要交换(例如在测试期间),我也可以交换整个工厂。

因此,以创建一个额外的类(工厂)为代价,我得到了更清晰的代码,并且不必担心使用全局静态时可能出现的奇怪错误。此外,在为测试提供模拟时,我确切地知道它需要什么模拟,并且不必模拟整个容器的类型。

这种方法还有一个优点,即现在,当一个模块被初始化时(仅适用于 Prism / Modularity),它不必注册它提供给 IoC 容器的所有对象类型。相反,它可以只注册它的 ServiceFactory,然后提供这些对象。

需要明确的是,模块的初始化类(实现 IModule)仍应在其构造函数中接收应用程序范围的 IoC 容器,以提供其他模块使用的服务,但容器不应侵入模块的类。

最后,我们这里有另一个很好的例子,说明额外的间接层如何解决问题。

于 2009-10-08T11:55:59.130 回答
14

将 IOC 容器放在进程的最高级别/入口点,并使用它在其下的所有内容中注入依赖项。

于 2009-09-01T22:02:10.543 回答
6

您可以注册容器本身并像其他所有依赖属性一样将其注入,如下所示:

IUnityContainer container = new UnityContainer();
container.RegisterInstance<IUnityContainer>(container);

需要访问它的类将具有以下属性:

private IUnityContainer unityContainer;
[Dependency]
public IUnityContainer UnityContainer
{
    get { return unityContainer; }
    set { unityContainer = value; }
}

因此,每当解析/构建此类的实例时,都会注入容器。

这更灵活,因为它适用于同一应用程序中的多个容器,而单例模式则无法做到这一点。

于 2009-01-26T16:25:37.573 回答
2

如果您的所有对象都需要对容器的引用,那么您应该考虑重新编写代码。虽然仍然比在任何地方调用 new 更可取,但它仍然分散了在整个代码中构建对象图的责任。有了这种用法,我觉得它更像是 ServiceLocator 而不是 IoC 容器。

于 2009-01-26T17:19:25.997 回答
0

另一种选择是使用CommonServiceLocator,尽管它可能是无意义的间接,但您可以将ServiceLocator.Current用作所有类都知道的实例

于 2009-04-20T16:13:45.757 回答
0

我在我的博客上有一篇关于这个主题的帖子,我正在使用类似 t3mujin 答案的东西。随意使用它(不要担心它与共享点相关......没关系):

http://johanleino.spaces.live.com/blog/cns!6BE273C70C45B5D1!213.entry

于 2009-05-23T16:10:09.207 回答