0

我有一个带有以下 Initialize() 方法的CustomersModule.cs :

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

}

我从容器中解析的类如下所示:

class CustomersPresenter
{
    private CustomersView view;
    private ICustomersRepository customersRespository;

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

TestWhatever类只是我创建的一个虚拟类:

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

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

}

然而,即使我从未注册过容器,容器也会愉快地解析 ,并且容器也会以某种方式找到TestWhatever,实例化它并将其注入.CustomersPresenterCustomersPresenter

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

所以这很好,但是容器还做了什么我不知道的事情,即它还能做什么我不知道的事情?例如,我是否可以从其他模块注入类,如果模块恰好被加载,容器将注入它们,如果没有,它会注入 null?

4

2 回答 2

3

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

class Fred { };

Fred f1 = new Fred();

Type t = typeof(Fred);

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

上面的最后一行实际上是发生了什么,类型 t 通过使用typeof你给的类型参数找到了Resolve

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

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

至于您对单独模块(程序集)的关注,如果您移动TestWhatever到另一个程序集,那不会改变您编写的代码行;这只是意味着您必须添加对另一个程序集的引用才能构建这个程序集。thenTestWhatever仍然是一个明确引用的可构造类型,所以它可以被 Unity 构造。

换句话说,如果你可以在代码中引用类型,你就可以得到一个Type对象,所以在运行时它是可以直接构造的。

回复评论:

如果删除 class TestWhatever,您将收到编译时错误,因为您在代码中引用了该类型。因此,这样做是不可能获得运行时的。

在这种安排中,解耦仍然有效,因为您可以注册 的特定实例TestWhatever,因此每次调用Resolve<TestWhatever>()都会获得相同的实例,而不是构造一个新实例。

于 2009-07-20T14:00:05.720 回答
2

之所以可行,是因为 Unity 是为它设计的。当您使用具体类型解析时,Unity 会查看它是否可以从容器中解析。如果它不能,那么它只是去实例化解析它的依赖关系的类型。这真的很简单。

于 2009-09-12T20:57:40.507 回答