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

Jim*_*_CS 11 c# wpf prism unity-container mvvm

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

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

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

public QuestionnaireView() 
{
    InitializeComponent(); 
}

public QuestionnaireView(QuestionnaireViewModel viewModel) : this() 
{
    this.DataContext = viewModel;
}
Run Code Online (Sandbox Code Playgroud)

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

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

public QuestionnaireView() 
{
    InitializeComponent(); 
}

[Dependency] 
public QuestionnaireViewModel ViewModel 
{
    set { this.DataContext = value; } 
}
Run Code Online (Sandbox Code Playgroud)

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

IUnityContainer container;
container.RegisterType<QuestionnaireViewModel>();
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Adi*_*ter 13

回答问题1和4

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

在这种情况下,注册viewmodel是多余的.但是,在使用依赖注入时,通常需要使用接口而不是类,因此构造函数看起来像这样:

public QuestionnaireView(IQuestionnaireViewModel viewModel)
{
    this.DataContext = viewModel;
}
Run Code Online (Sandbox Code Playgroud)

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

container.RegisterType<IQuestionnaireViewModel, QuestionnaireViewModel>();
Run Code Online (Sandbox Code Playgroud)

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

回答问题2

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

回答问题3

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

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

  • @JohnMcDonald依赖注入可以用于viewmodel以外的许多东西.通过在具体类上使用接口,您可以轻松切换代码中的依赖项.例如,今天您可以使用`Log4NetLogger`来进行日志记录,但明天您可以使用`EnterpriseLibraryLogger`.如果您使用`ILogger`进行注射,那么您需要做的就是更改将记录器注册到容器的行.如果还没有,则必须更改并重新编译使用该记录器的每个类. (4认同)