有人可以解释Prism决心中发生的魔力吗?方法? [英] Can someone explain the magic going on in Prism's resolve<> method?

查看:91
本文介绍了有人可以解释Prism决心中发生的魔力吗?方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 CustomersModule.cs ,具有以下Initialize()方法:

  public void Initialize()
{
container.RegisterType< ICustomersRepository,CustomersRepository>(new ContainerControlledLifetimeManager());
CustomerPresentercustomersPresenter = this.container.Resolve< CustomersPresenter>();

}

我解析的容器看起来像这样:

  classCustomersPresenter 
{
privateCustomersView视图;
私人ICustomersRepository客户存储库;

publicCustomersPresenter(CustomersView视图,
ICustomersRepositoryCustomersRepository,
Testever testWhatever)
{
this.view = view;
this.customersRespository = customerRepository;
}
}

TestWhat 类是我创建的只是一个虚拟类

 公共类TestWhatever 
{
公共字符串Title {get;组; }

public TestWhatever()
{
Title =这是标题;
}

}

但容器愉快地会解决 CustomersPresenter ,即使我从未注册过,并且容器以某种方式找到 TestWhat都实例化了它,并将其注入到 CustomersPresenter



我很惊讶地意识到这一点,因为我在Prism文档中找不到任何地方,该文档明确指出容器是非常自动的。



所以这很好,但是容器还能做什么呢?不知道,即我不知道还能做什么? 例如,我可以从其他模块中注入类吗,如果恰巧加载了模块,容器将注入它们,如果不是,它将注入null?

解决方案

没有神奇的事情发生。您是在指定具体类型,因此自然可以解决它们,因为如果有 Type 对象,我们可以在其上调用构造函数。

 类Fred {}; 

Fred f1 =新Fred();

类型t = typeof(Fred);

Fred f2 =(Fred)t.GetConstructor(Type.EmptyTypes).Invoke(null);

上面的最后一行实际上是发生的情况,通过使用<$ c $找到了类型t c> typeof 输入解析的类型参数。



如果类型不能由new构造(因为它位于某些未知的单独代码库中),那么您将无法将其作为类型参数提供给 Resolve



在第二种情况下,它是构造函数注入,但是它仍然是已知的具体可构造类型。通过反射,Unity框架可以获得构造函数的所有参数类型的数组。 TestWhatever 类型是可构造的,因此构造什么没有歧义或困难。



关于您的关注关于单独的模块(程序集),如果将 TestWhatever 移至另一个程序集,则不会更改您编写的代码行;这仅意味着您必须添加对另一个程序集的引用才能构建该程序集。然后 TestWhatever 仍然是明确引用的可构造类型,因此它可以由Unity构造。



,如果您可以在代码中引用类型,则可以获取 Type 对象,因此在运行时它将可以直接构造。



回复评论:



如果您删除类 TestWhat ,您将得到一个编译时错误,因为您在代码中引用了该类型。因此,将无法获得运行时的结果。 c $ c> TestWhatever ,因此每次对 Resolve< TestWhatever>()的调用都会得到相同的实例,而不是构造一个新的实例。 / p>

I've got a CustomersModule.cs with the following Initialize() method:

public void Initialize()
{
    container.RegisterType<ICustomersRepository, CustomersRepository>(new ContainerControlledLifetimeManager());
    CustomersPresenter customersPresenter = this.container.Resolve<CustomersPresenter>();

}

The class I resolve from the container looks like this:

class CustomersPresenter
{
    private CustomersView view;
    private ICustomersRepository customersRespository;

    public CustomersPresenter(CustomersView view, 
        ICustomersRepository customersRepository, 
        TestWhatever testWhatever)
    {
        this.view = view;
        this.customersRespository = customersRepository;
    }
}

The TestWhatever class is just a dummy class I created:

public class TestWhatever
{
    public string Title { get; set; }

    public TestWhatever()
    {
        Title = "this is the title";
    }

}

Yet the container happily resolves CustomersPresenter even though I never registered it, and also the container somehow finds TestWhatever, instantiates it, and injects it into CustomersPresenter.

I was quite surprised to realize this since I couldn't find anywhere in the Prism documentation which explicitly stated that the container was so automatic.

So this is great, but it what else is the container doing that I don't know about i.e. what else can it do that I don't know about? For example, can I inject classes from other modules and if the modules happen to be loaded the container will inject them, and if not, it will inject a null?

解决方案

There is nothing magical going on. You are specifying concrete types, so naturally they are resolvable, because if we have the Type object, we can call a constructor on it.

class Fred { };

Fred f1 = new Fred();

Type t = typeof(Fred);

Fred f2 = (Fred)t.GetConstructor(Type.EmptyTypes).Invoke(null);

The last line above is effectively what happens, the type t having been found by using typeof on the type parameter you give to Resolve.

If the type cannot be constructed by new (because it's in some unknown separate codebase) then you wouldn't be able to give it as a type parameter to Resolve.

In the second case, it is constructor injection, but it's still a known concrete constructable type. Via reflection, the Unity framework can get an array of all the Types of the parameters to the constructor. The type TestWhatever is constructable, so there is no ambiguity or difficulty over what to construct.

As to your concern about separate modules (assemblies), if you move TestWhatever to another assembly, that will not change the lines of code you've written; it will just mean that you have to add a reference to the other assembly to get this one to build. And then TestWhatever is still an unambiguously refeferenced constructable type, so it can be constructed by Unity.

In other words, if you can refer to the type in code, you can get a Type object, and so at runtime it will be directly constructable.

Response to comment:

If you delete the class TestWhatever, you will get a compile-time error, because you refer to that type in your code. So it won't be possible to get a runtime by doing that.

The decoupling is still in effect in this arrangement, because you could register a specific instance of TestWhatever, so every call to Resolve<TestWhatever>() will get the same instance, rather than constructing a new one.

这篇关于有人可以解释Prism决心中发生的魔力吗?方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆