保持模型和ViewModel同步的最佳实践

时间:2011-02-04 22:51:27

标签: silverlight wcf mvvm synchronization

我正在开发一个大型Silverlight应用程序,它使用双工Net.TCP与WCF后端通信。我正在将这个应用程序从MVC方法转移到MVVM。但是,我正在努力使用正确的方法来实现我的ViewModel。我们正在为我们的模型使用WCF生成的代理,这个代理非常复杂,涉及许多类,大量集合以及各种多对多关系。例如,用户可以属于许多房间,房间可以有许多用户,用户可以有许多SharedFiles,并且每个SharedFile可以与用户当前所属的任何房间共享。那种事。

最重要的是,由于我们在双工模式下使用WCF,因此可以由最终用户或后端的WCF服务触发对模型的更改。换句话说,我们使用的模型比您在各种MVVM书籍/文章/博客文章中看到的典型“模型”复杂几个数量级。这就是问题所在,因为保持我们的ViewModel层与底层模型层同步变得有点麻烦。

这是一个典型的问题。新的“用户”加入“房间”,因此WCF服务向房间中的所有其他用户发出“SessionAdded”通知。 SessionAdded通知带有一个Session对象,该对象具有链接的Room和链接的User对象。从WCF服务反序列化的Room对象与本地客户端上的Room对象基本相同,并且可能具有大部分相同的数据,但它肯定没有 all 相同的数据,至少有一些数据(比如它的null Whiteboards集合)肯定是错的。所以我们需要以某种方式获取这些传入的数据并将其合并到我们现有的模型中。然后我们需要在每个新对象的基础上创建ViewModel,和/或用新对象和/或它们的数据更新现有的ViewModel。

现在我们通过让各种ViewModel响应相关的WCF通知事件来处理这个问题,并尽力修复它们的底层模型和相关的视图模型。我们已经找到了一些技巧,比如一个SynchronizedObservableCollection(模糊地像一个here),它监视(说)Room.Sessions ObservableCollection并自动创建相应的SessionViewModel并将它们放在RoomViewModel.SessionViewModels集合中。我们还使用ViewModelFactory来缓存视图模型,并确保包装给定Session的SessionViewModel保持不变,即使底层Session对象被更改了。 (如果重要的话,我们使用的是viewmodel-first方法,因为我们需要的很大一部分是为了响应由我们的WCF通知触发的ViewModel中的更改而创建新的UI元素。)

所有这一切都有效。基本上。大多数时候。你懂。但是要维护的代码很多,而且很容易出错。单元测试很方便,只要你能记住应该发生的事情,但是当你完成处理你的第20次级联CollectionChanged事件时,很难跟踪所有这些如何组合在一起以及你首先测试的是什么。换句话说,这一切都非常脆弱。

在我看来,这是许多人必须遇到的那种情景,我很好奇其他人是如何面对它的。我可以想到一些方法可能会让它变得更好:

(1)将客户端模型视为一种需要保持完全一致的数据库,并实现客户端数据访问层,其作用是保持模型的一致性。无论是来自用户还是服务器,对模型的所有更新都需要通过该层。它有点像实体框架,因为myRoom.Users.Add(myUser)会自动设置myUser.Room = myRoom,反之亦然,等等。 (这尤其是某个地方应该已经开发出来的部分,尽管我还没有找到它。)

(2)倾向于TrussObtics,以保持所有部分同步。不太确定它是如何工作的,但理论上听起来应该是可能的。

而且......还有什么?我很好奇用于解决这个问题的模式或框架。

1 个答案:

答案 0 :(得分:3)

我理解您的痛苦 - 我目前正在使用MVVM模式开发复杂的数据可视化应用程序。要问自己一个非常重要的问题是,“视图模型是否会在您使用它的任何地方增加价值?”,换句话说,是否只有将模型层上的属性转发给您的视图?

我经常发现代码区域,通常是详细级别(例如Person对象的属性,Age,Name,Forename),其中视图模型实际上根本没有添加任何值,而在更多课程级别,它通过构建视图/窗口等来增加价值......

我倾向于采用MVVM的自适应方法,在顶级(Windows,窗格,表格)我总是有一个视图模型,但如果视图模型的某些部分非常简单,视图模型没有增加任何价值,我直接将它们暴露给视图。此外,在某些情况下,您需要将模型直接暴露给视图以获得更好的性能。

最后,如果您发现需要重新引入视图模型来解决棘手的绑定问题,我写了一个简单的模式,mini-MVVM,它应用了本地视图模型:

http://www.scottlogic.co.uk/blog/colin/2009/08/the-mini-viewmodel-pattern/

希望有所帮助。