这在Prism / Unity中意味着什么:Container.Resolve <shellpresenter>()</shellpresenter>

时间:2009-03-11 13:13:21

标签: inversion-of-control unity-container prism containers

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

这有什么区别:

ShellPresenter presenter = new ShellPresenter();

和此:

ShellPresenter presenter = Container.Resolve<ShellPresenter>();
  • 我理解第二个例子是将容器视为工厂,走到它说“我需要一个ShellPresenter类型的实例化对象”。
  • 但是如果,例如,我需要发送参数,相当于“new ShellPresenter(1,true)”等等。
  • 由于必须告诉Container有关ShellPresenter的信息,我希望在项目的某个地方找到ShellPresenter类在容器中注册的地方,例如:我在期待

类似的东西:

Container.RegisterType<IShellPresenter, ShellPresenter>();

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

这里的任何指示/讨论都会有所帮助。

原因不明的答案:

所以,在bootstrapper中,当我注册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 个答案:

答案 0 :(得分:10)

如果你试图解决一个具体的类并且没有注册实例或子类来满足它,那么Unity将为你构造一个具体类的实例,解决它所拥有的任何依赖项。

因此,当您要求ShellPresenter并且尚未注册时,Unity刚刚为您提供ShellPresenter,并将ShellView作为参数。

答案 1 :(得分:5)

您了解基础知识。

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

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

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

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

我不能代表温莎,StructureMap或其他人,这可能允许你这样做。我甚至不能明确地断言Unity没有办法做到这一点,因为我有相当的新意,但IIRC Chris Tavares--基本上建立了Unity--不时在这里闲逛,所以也许他会匆匆离开回答这一个: - )