在MVC中,这是非常直截了当的:
客户端发出请求,控制器要求buiseness逻辑做一些花哨的东西,buiseness逻辑要求存储库返回一些数据,然后存储库返回数据和buiseness逻辑负责将数据从实体转换为viewmodel,返回给客户端。
在MVVM中我几乎迷失了,因为viewmodel本身负责向buiseness逻辑发出请求,没有像Controller这样的“中间层”。我可以在buiseness逻辑项目中实现映射器,但由于viewmodels负责向数据提供buiseness逻辑,因此它将创建循环引用。
那么我必须在哪里实现这种“神奇”呢?
答案 0 :(得分:2)
我会尝试用一个简单的例子给出一些背景信息。
请注意,下面的所有代码都只是概念性的,并且写在这里而不是VS.
将ViewModel视为模型的包装器。 您的模型由属性公开,因此您可以从视图中绑定它或它的属性。
您的ViewModel:
public class SomeEntityViewModel : NotificationObject
{
private SomeEntity _someEntity;
public SomeEntity SomeEntity
{
get{ return _someEntity;}
set
{
_someEntity = value;
RaisePropertyChanged("SomeEntity");
}
}
}
现在假设您向服务器发送请求并等待响应。
我们还假设您有一个更高的对象(如父ViewModel)启动您的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);
}
}
SomeEntityContainerView,其中SomeEntityContainerViewModel是DataContext:
<UserControl>
<Button Command="{Binding RequestNewEntityCommand}" />
<ItemsControl ItemsSource="{Binding Items}" />
</UserControl>
您的SomeEntityView,其中SomeEntityViewModel是DataContext:
<UserControl>
<TextBlock Text="{Binding SomeEntity.Name}" />
</UserControl>
在其最简单的设计中:
您的模型必须是“愚蠢的”,只有数据。 ViewModel是最接近Controller的等价物,它将处理逻辑,它是在视图模型中包装(不转换)模型的组件。
在上面的示例中,我们有一个更高的对象,父ViewModel启动我们的ViewModel。
它等同于Controller的范围,在DOM中有其他嵌套控制器。
答案 1 :(得分:0)
基于mvvm-light参考,我在这里假设一个WPF应用程序。 我在第1段你提到你的业务逻辑(我将这里称之为服务)负责转换为视图模型。我会说服务应该不了解视图。因此,在这种情况下,控制器(或由控制器或模型绑定器调用的映射器)将处理映射。
在MVVM中(我的意思是在尝试为您绘制比较时),ViewModel的作用非常类似于控制器,并获取模型,映射和绑定到可观察对象。它也是绑定到视图的模型(mvc中经常使用的视图模型)。
所以我认为这里的技巧是移动映射应该发生的位置。服务不应该对意见有任何了解。他们没有与观点相关联,这是一件好事。
答案 2 :(得分:0)
在MVVM中,您所指的“业务层”是“模型” - 事实上,视图模型之后的任何内容都被视为“模型”的一部分。然而,在我做过的任何工作中,我总是将此模型拆分为 n-tier ,通常使用控制器样式类,该类使用服务从数据存储库中检索数据实体。
将实体/模型转换为viewmodels的位置?
严格来说,你没有。视图模型可以包含实体(即VM具有ObservableCollection),或者视图模型可以包装实体(在列表控件中很有用,您可能需要显示选项)或者基于每行执行操作。)
对于一个实体的MVC方法比MVVM有点脏,你最终会得到一个更丰富的商业模式而不是一个好的精益实体。在MVVM中,“丰富性”主要由视图模型拆分和处理,并且您尝试使数据实体尽可能简单(是的,您可以在实体中包含诸如验证之类的内容,但您只应在必要时执行此操作,其他验证应该在VM或模型中的某个地方进行验证。答案 3 :(得分:0)
你的问题是错误的。视图模型表示用户与应用程序交互的逻辑,因此问题应该是“视图模型在用户交互请求时如何获取实体和模型?”。答案是:“使用依赖注入框架,例如Ninject”。这允许您将实体范围扩展到WPF应用程序中的页面,MVC或WCF应用程序中的Web请求,任何外部控制台实用程序中的单例或测试框架中的模拟对象......以及所有视图模型都不知道或关心关于如何创建这些实体或提供它们的服务或在内部工作。