18

(来自Prism V2 StockTrader 示例应用程序中的StockTraderRIBootstrapper.cs文件)

这有什么区别:

ShellPresenter presenter = new ShellPresenter();

还有这个:

ShellPresenter presenter = Container.Resolve<ShellPresenter>();
  • 我知道第二个示例是将容器视为工厂,走到它面前说“我需要一个 ShellPresenter 类型的实例化对象”。
  • 但是,如果,例如我需要发送参数,什么是“new ShellPresenter(1, true)”等的等价物呢?
  • 而且由于容器必须被告知 ShellPresenter,我希望在项目中的某个地方找到 ShellPresenter 类向容器注册的地方,例如,我期待

像这样的东西:

Container.RegisterType<IShellPresenter, ShellPresenter>();

但无处可寻。那么容器如何知道这些类型以便它能够解决它们呢?我在自己的项目中重建了它并得到“依赖项的解决失败”错误,那么我需要在哪里注册这个依赖项?

这里的任何方向/讨论都会有所帮助。

无法解释的答案:

因此,在引导程序中,当我注册 Shell 本身时:

protected override void ConfigureContainer()
{
    Container.RegisterType<IShellView, Shell>();
    base.ConfigureContainer();
}

那么 Container 可以解析 ShellPresenter 类型。那么我注册Shell类型的时候, ShellPresenter类型是怎么注册的呢?

令人惊讶的答案:

好的,事实证明,您不必注册您尝试解析的类型,但您必须注册传递给您尝试解析的类型的构造函数的参数(接口)类型,即因为我注入IShellView 接口到我的 ShellPresenter 的构造函数中,我需要注册 IShellView 类型而不是 IShellPresenter 类型:

public ShellPresenter(IShellView view) ...

我通过尝试解析类型Tester对此进行了测试:

Tester tester = Container.Resolve<Tester>();

只要我将SomeClass注入它的构造函数:

public Tester(ISomeClass someClass)

在向容器注册SomeClass之前,我得到未解决的依赖错误:

Container.RegisterType<ISomeClass, SomeClass>();

然后它工作。这既令人惊讶,又具有教育意义。需要沉下心来。我要去喝杯咖啡,想一想。

如果有人能详细说明为什么会这样,将不胜感激。

4

4 回答 4

12

如果您尝试解析具体类并且没有注册实例或子类来满足它,那么 Unity 将为您构造具体类的实例,解决它所具有的任何依赖关系。

因此,当您请求 ShellPresenter 并且尚未注册时,Unity 会为您新建一个 ShellPresenter,并以 ShellView 作为参数。

于 2009-04-21T03:04:04.243 回答
6

你了解基本情况。

有用于解析需要构造函数参数的类型的重载。或者,您始终可以将您的类型编码为具有无参数构造函数。

DI 容器的意义在于,您可以配置它们以更改为特定接口解析的类型,而无需重新编译您的软件。您提供的用于配置提供程序的代码示例不能在运行时更改。这就是为什么大多数依赖注入器允许您在 app.config/web.config/其他一些外部配置文件中配置它们。这样您就可以重新配置您的应用程序以注入不同的类型而无需重新编译,这是 Unity 等 DI 框架的真正强大之处。

于 2009-03-11T13:26:45.387 回答
1

好吧,我无法回答 Untiy,但对于 Castle Windsor,注册可以在 app.config/web.config 文件中。还可以在配置 xml 中添加参数。

这允许您更改对象的实现和配置,而无需重新编译您的应用程序。

于 2009-03-11T13:25:05.237 回答
1

在 Unity 中,确实有一个Container.RegisterType<TFrom, TTo>()方法集可以在运行时注册类型。使用 XML 配置文件可能更常见,但两者都可以。

有趣的是,在 Unity 中没有Container.Resolve<T>(params object[] parameters)-type 方法来解析具有特定构造函数参数值的类型。Unity 建立在 ObjectBuilder 之上,ObjectBuilder 是 P&P 团队用于进行对象构造和连接的库(IIRC,它最初是为 ObjectSpaces 编写的,但现在已得到显着增强)。ObjectBuilder 使您能够以各种方式注入依赖项,包括通过构造函数,因此您可以说 - 例如 - 您可以将它所依赖的类型的新实例传递给已解析类型的构造函数;但该类型也必须注册。您还可以传递注册类型的实例(注册实例/单例等)。但是 AFAICS 没有办法简单地给它一个传递的值。

我认为这样做在某种程度上违背了 IoC 的理念,这就是他们不提供这种设施的原因。理论上,容器应该能够在任何给定情况下为您提供完整的对象图,因此您永远不必传入参数,并使您的对象依赖于构造函数参数而不是可注入对象依赖项(容器将解析为你)被视为糟糕的设计。

我不能代表 Windsor、StructureMap 或其他人,这可能会让你这样做。我什至不能直截了当地说 Unity 没有办法做到这一点,因为我对它还很陌生,但是 IIRC Chris Tavares - 他基本上是 Unity 的开发者 - 不时在这里闲逛,所以也许他会顺便过来回答这个:-)

于 2009-03-11T14:07:02.060 回答