Prism,将Views和ViewModels与Unity连接,试图理解它

使用Unity创建视图和视图模型

使用Unity作为dependency injection容器类似于使用MEF,并且支持基于属性和基于构造函数的注入。 主要区别在于通常不会在运行时隐式发现类型; 相反,他们必须在容器中注册。

通常,您在视图模型上定义接口,以便视图模型的特定具体类型可以与视图分离。 例如,视图可以通过构造函数参数定义其对视图模型的依赖性,如此处所示。 C#

public QuestionnaireView() { InitializeComponent(); } public QuestionnaireView(QuestionnaireViewModel viewModel) : this() { this.DataContext = viewModel; } 

默认的无参数构造函数是允许视图在设计时工具(如Visual Studio和Expression Blend)中工作所必需的。

或者,您可以在视图上定义只写视图模型属性,如此处所示。 Unity将实例化所需的视图模型,并在实例化视图后调用属性setter。 C#

 public QuestionnaireView() { InitializeComponent(); } [Dependency] public QuestionnaireViewModel ViewModel { set { this.DataContext = value; } } 

视图模型类型已在Unity容器中注册,如此处所示。 C#

 IUnityContainer container; container.RegisterType(); 

然后可以通过容器实例化视图,如此处所示。 C#

 IUnityContainer container; var view = container.Resolve(); 
  1. 如果我省略了有关注册ViewModel和实例化View的代码的最后部分,并且只使用将ViewModel挂钩到View的两种方法中的任何一种(使用构造函数或使用属性),那么看起来是ViewModel和View似乎一切都运转良好。 那么代码注册ViewModel并实例化View的需求是什么?

  2. 第一个例子,使用构造函数钩住View和ViewModel,没有提到Unity的全部,所以Unity实际上在这里使用了吗?

  3. 使用基于属性的注射比使用基于构造的注射有任何优势还是它们完全相同?

  4. 文本的第一部分说“*通常,您在视图模型上定义一个接口,以便视图模型的特定具体类型可以与视图分离”,然后给出一个示例。 然而,这个例子根本没有提到接口。 这里发生了什么,我错过了什么?

回答问题1和4

在您的示例中,viewmodel的类型为QuestionnaireViewModel ,它是一个具体的类。 由于它是一个具体的类,当你使用container.Resolve()解析视图时,unity将通过在幕后调用container.Resolve()来为你实例化viewmodel。

在这种情况下,注册viewmodel是多余的。 但是,在使用dependency injection时,您通常希望使用接口而不是类,因此构造函数看起来像这样:

 public QuestionnaireView(IQuestionnaireViewModel viewModel) { this.DataContext = viewModel; } 

既然你的构造函数接收了一个接口而不是一个类作为参数,Unity就不知道你想要使用哪个接口实现。 要告诉Unity,您需要将viewmodel注册到容器:

 container.RegisterType(); 

所以现在当你解决你的观点时,Unity会查找它应该用作IQuestionnaireViewModel实现的IQuestionnaireViewModel ,看看它是QuestionnaireViewModel并使用它。

回答问题2

正在使用Unity,因为为了使构造函数获取其参数,您需要使用容器来解析视图。 如果您使用new QuestionnaireView()自己实例化视图,则不使用Unity,即不会发生构造函数或属性注入。

回答问题3

我认为这主要取决于什么更舒适以及需要使用注射成员的地方。 很多时候,您只想在构造函数中设置局部变量,而不是仅为执行注入创建属性。

关于属性注入的一个好处是,您可以对使用new而不是container.Resolve<>()创建的实例使用container.BuildUp()方法。 这样,即使在创建之后,您也可以将成员注入属性 – 这是构造函数注入无法做到的事情。