C# 在MVVM中,在何处将实体/模型转换为viewmodels?

C# 在MVVM中,在何处将实体/模型转换为viewmodels?,c#,mvvm,mvvm-light,C#,Mvvm,Mvvm Light,在MVC中,这是非常超前的: 客户机发出请求,控制器要求Buisense logic执行一些奇特的操作,Buisense logic要求存储库返回一些数据,然后存储库返回数据,Buisense logic负责将数据从实体转换为viewmodels,然后返回给客户机 在MVVM中,我几乎不知所措,因为viewmodel本身负责向构建逻辑发出请求,所以没有像控制器那样的“中间层”。我可以在BuisensLogic项目中实现映射器,但由于viewmodels负责向BuisensLogic请求数据,因此

在MVC中,这是非常超前的:

客户机发出请求,控制器要求Buisense logic执行一些奇特的操作,Buisense logic要求存储库返回一些数据,然后存储库返回数据,Buisense logic负责将数据从实体转换为viewmodels,然后返回给客户机

在MVVM中,我几乎不知所措,因为viewmodel本身负责向构建逻辑发出请求,所以没有像控制器那样的“中间层”。我可以在BuisensLogic项目中实现映射器,但由于viewmodels负责向BuisensLogic请求数据,因此它将创建循环引用


那么,我必须在哪里实现这一“神奇”呢?

基于mvvm灯光参考,我假设这里有一个WPF应用程序。 在您提到的第一段中,您的业务逻辑(我在这里称之为服务)负责转换为视图模型。我要说的是,服务部门应该不知道这个观点。因此,在这种情况下,控制器(或由控制器或模型绑定器调用的映射器)将处理映射

在MVVM中(我在这里的观点是试图为您进行比较),ViewModel的行为非常类似于控制器,它获取模型,映射并绑定到可观察对象。然后是绑定到视图的模型(mvc中经常使用的视图模型)

所以我认为这里的技巧是移动映射应该发生的地方。服务部门不应了解任何视图。他们没有与当时的观点相结合,这是一件好事

在MVVM中,您所指的“业务层”是“模型”——实际上,viewmodel之后的任何内容都被视为“模型”的一部分。然而,在我所做的任何工作中,我总是将此模型拆分为n层,通常使用一个控制器样式的类,该类使用服务从数据存储库检索数据实体

在何处将实体/模型转换为viewmodels

严格地说,你没有。viewmodels可以包含实体(即VM具有它们的ObservableCollection),或者viewmodel可以包装实体(在列表控件中很有用,您可能需要按行显示选项或执行操作)


对一个实体来说,MVC方法比MVVM更脏,你最终会得到一个更丰富的商业模式,而不是一个漂亮的精益实体。在MVVM中,“丰富性”主要是由viewmodel分割和处理的,您尝试使数据实体尽可能简单(是的,您可以在实体中包括验证之类的内容,但您应该只在必要时进行,其他时候验证应该在VM中或模型中的某个地方进行).

你的问题绕错了方向。视图模型表示用户与应用程序交互背后的逻辑,因此问题应该是“当用户交互请求实体和模型时,视图模型如何获取实体和模型?”。答案是:“使用依赖注入框架,例如Ninject”。这允许您将实体的范围扩展到WPF应用程序中的页面,以及MVC或WCF应用程序中的web请求,对于任何外部控制台实用程序中的单例或测试框架中的模拟对象……以及所有这些,您的视图模型都不知道或不关心这些实体或提供它们的服务是如何在内部创建或工作的。

我将试着用一个简单的示例给出一些上下文

请注意,下面的所有代码都是概念性的,都是在这里编写的,而不是在VS中编写的。

将ViewModel视为模型的包装器。 您的模型由属性公开,因此您可以从视图绑定到它或它的属性

您的ViewModel:

  public class SomeEntityViewModel : NotificationObject
  {
       private SomeEntity _someEntity;
       public  SomeEntity SomeEntity
       {
           get{ return _someEntity;}
           set
           {
               _someEntity = value;
               RaisePropertyChanged("SomeEntity");
           }  
       }  
  } 
现在让我们假设您向服务器发送请求并等待响应

我们还假设您有一个更高的对象(如父视图模型)来启动VM:

  public class SomeEntityContainerViewModel : NotificationObject
  {
      public ObservableCollection<SomeEntityViewModel> Items;

      public void async OnRequestNewEntity() 
      {
         SomeEntity newEntity = await _someEntityService.CreateSomeEntityAsync();
         var vm = new SomeEntityViewModel{ SomeEntity = newEntity};
         Items.add(vm);
      }
  }
公共类SomeEntityContaineServiceModel:NotificationObject
{
公众可观察到的收集项目;
public void异步OnRequestNewEntity()
{
SomeEntity newEntity=await _someEntityService.CreateSomeEntityAsync();
var vm=new-SomeEntityViewModel{SomeEntity=newEntity};
添加项目(vm);
}
}
SomeEntityContainerView的SomeEntityContainerViewModel是其数据上下文:

  <UserControl>
      <Button Command="{Binding RequestNewEntityCommand}" />
      <ItemsControl ItemsSource="{Binding Items}" />
  </UserControl>
    <UserControl>
        <TextBlock Text="{Binding SomeEntity.Name}" />
    </UserControl>

SomeEntityView的SomeEntityViewModel是其数据上下文:

  <UserControl>
      <Button Command="{Binding RequestNewEntityCommand}" />
      <ItemsControl ItemsSource="{Binding Items}" />
  </UserControl>
    <UserControl>
        <TextBlock Text="{Binding SomeEntity.Name}" />
    </UserControl>

最简单的设计:

您的模型需要是“哑的”,只有数据。 您的ViewModel与控制器最接近,它将处理逻辑,并且是将在视图模型中包装(而不是转换)您的模型的组件

在上面的示例中,我们有一个更高的对象,即启动ViewModel的父ViewModel


这相当于一个控制器的作用域,该作用域在DOM中有其他嵌套的控制器

您的业务实体来自哪里。远程服务器?在请求它们时,在回调函数中,将它们封装在您希望UI使用的UI模型中。这是对DB的简单请求。我想要的是让我的BL返回ViewModels,而不是实体。因此viewmodel本身应该负责Mvvm中的转换?是的,我想是的。例如,在javascript虚拟机中,一个方法将从web API获取数据并填充虚拟机。VM负责从服务获取数据并填充自身。我使用它作为一个例子,因为在客户机-服务器设置中更容易将其分离出来,但其原理与WPF中的MVVM相同。该服务负责提供模型。回答得好,我赞赏你尝试回答这个问题-由于定义冲突,这不是一个容易的话题。但是,我要明确指出,VM(在MVVM中)不是控制器的等价物。你可以这样编码,但是