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

发布于 2024-07-14 19:36:30 字数 1902 浏览 7 评论 0原文

(来自 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();
}

然后容器可以解析 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>();

然后它就可以工作了。 这既令人惊讶又具有教育意义。 需要深入思考。我要去喝杯咖啡,思考一下这个问题。

如果有人能详细说明为什么会出现这种情况,我们将不胜感激。

(from the StockTraderRIBootstrapper.cs file in the Prism V2 StockTrader example app)

What is the difference between this:

ShellPresenter presenter = new ShellPresenter();

and this:

ShellPresenter presenter = Container.Resolve<ShellPresenter>();
  • I understand the second example is treating the container like a factory, walking up to it saying "I need an instantiated object of type ShellPresenter".
  • But what if, e.g. I need to send parameters, what would be the equivalent of "new ShellPresenter(1, true)" etc.?
  • And since the Container has to be told about the ShellPresenter, I expected to find somewhere in the project a place where the ShellPresenter class being registered with the container, e.g. I was expecting

something like this:

Container.RegisterType<IShellPresenter, ShellPresenter>();

but found it nowhere. So how does the container get to know about these types so it can .Resolve them? I rebuilt this in its own project and get a "Resolution of the dependency failed" error, where do I need to register this dependency then?

Any direction/discussion here would be helpful.

Unexplained Answer:

So, in the bootstrapper, when I register the Shell itself:

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

then the Container can resolve the ShellPresenter type. So how is the ShellPresenter type registered when I register the Shell type?

The Surprising Answer:

Ok, so it turns out that you don't have to register the type you are trying to resolve but you do have to register the parameter (interface) types passed to the constructor of the type you are trying to resolve, i.e. since I inject the IShellView interface into my ShellPresenter's constructor, I needed to register the IShellView type and not the IShellPresenter type:

public ShellPresenter(IShellView view) ...

I tested this by trying to resolve the type Tester:

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

As long as I inject SomeClass into its constructor:

public Tester(ISomeClass someClass)

I get unresolved dependency errors until I register SomeClass with the container:

Container.RegisterType<ISomeClass, SomeClass>();

Then it works. This is as surprising as it is educational. Needs to sink in. I'm going to go get a coffee and think about this for awhile.

If anyone can elaborate on why this is the case, it would be much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

埋葬我深情 2024-07-21 19:36:30

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

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

If you try to resolve a concrete class and have not registered an instance or sub-class to satisfy it, then Unity will construct an instance of the concrete class for you, resolving any dependencies that it has.

So when you ask for ShellPresenter, and haven't registered it, Unity just new's up a ShellPresenter for you with the ShellView as a parameter.

魔法少女 2024-07-21 19:36:30

你了解基础知识。

有一些重载用于解析需要构造函数参数的类型。 或者,您始终可以对类型进行编码以使其具有无参数构造函数。

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

You understand the basics.

There are overloads for resolving types that require constructor arguments. Alternatively, you can always code your types to have a parameterless constructor.

The point of DI containers is that you can configure them to change the type that gets resolved for a particular interface without recompiling your software. The code example you provided for configuring the provider can't be changed at runtime. That's why most dependency injectors allow you to configure them in app.config/web.config/some other external configuration file. That way you can reconfigure your app to inject a different type without recompiling, which is the true power of DI frameworks like Unity.

我做我的改变 2024-07-21 19:36:30

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

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

Well, I can't answer for Untiy, but for Castle Windsor, the registration could be in the app.config/web.config file. There is also the ability to add the parameters in the config xml.

This allows you to change the implementation and configuration of the object without having to recompile you application.

放我走吧 2024-07-21 19:36:30

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

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

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

我不能代表 Windsor、StructureMap 或其他软件,它们可能允许您执行此操作。 我什至不能明确地说 Unity 没有办法做到这一点,因为我对这方面还算陌生,但是 IIRC Chris Tavares(Unity 的基本构建者)会时不时地在这里闲逛,所以也许他会过来并且回答这个问题:-)

In Unity, there is indeed a Container.RegisterType<TFrom, TTo>() method set that registers types at runtime. It's probably more common to do it using an XML configuration file, but either works.

Interestingly, in Unity there is no Container.Resolve<T>(params object[] parameters) -type method to resolve a type with specific constructor parameter values. Unity is built on top of ObjectBuilder which is the P&P team's library for doing object construction and wireup (IIRC it was originally written for ObjectSpaces but has been significantly enhanced now). ObjectBuilder gives you the ability to inject dependencies in various ways, including via the constructor, so you could say - for example - that you would pass a new instance of a type it's dependent on into the constructor of a resolved type; but that type would also have to be registered. You can also pass instances of registered types (a registered instance / singleton etc). But AFAICS there is no way to simply give it a value to pass in.

I think doing that would go against the philosophy of IoC to some extent, which is why they don't provide that facility. The container should, in theory, be able to give you a complete object graph in any given circumstance, so you should never have to pass parameters in, and making your objects dependent on constructor parameters other than injectable object dependencies (which the container will resolve for you) is seen as Bad Design.

I can't speak for Windsor, StructureMap or the others, which may allow you to do this. I can't even say categorically that Unity has no way to do it since I'm reasonably new at it, but IIRC Chris Tavares - who basically built Unity - hangs out here from time to time, so maybe he'll drop by and answer this one :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文