[Silverlight入门系列]使用MVVM模式(8):ViewModel进一步分离出Services
在上一讲中介绍了MVVM的核心概念,运用MVVM模式可以分离视图、视图逻辑和模型,提高可测试性和可维护性等,但如果一个视图比较复杂,仔细Review一下其ViewModel你会发现非常庞大臃肿复杂,而且部分代码逻辑不可重用,例如另外一个ViewModel想重用其中的部分代码逻辑而不是整个重用,就没有办法。所以最好进一步分离ViewModel的关注点,分离出Services实现IServcie接口,让Service去做一些可重用的工作,分离出一些可重用的操作,这样其他的ViewModel就可以用Service来重用ViewModel的部分逻辑了。原来的ViewModel关注点可以聚焦在用户界面交互(绑定)和视图展现逻辑上。下面这个图描述了分离ViewModel关注点的关系:
例如,我们在ViewModel中有一段逻辑是用DomainContext从WCF RIA Service获取数据,现在我们把它分离出去,就叫MyDataService,实现以下接口IMyDataService:
接口IMyDataService
1: public interface IMyDataService
2: {
3: void GetMyEntities(Action<ObservableCollection<MyEntity>> getMyEntityCallback);
4: }
类MyDataService实现以上接口
1: [Export(typeof(IMyDataService))]
2: [PartCreationPolicy(CreationPolicy.Shared)]
3: public class MyDataService : IMyDataService
4: {
5: private MyEntityDomainContext Context { get; set; }
6: private LoadOperation<MyEntity> _operation;
7: private Action<ObservableCollection<MyEntity>> _getMyEntityCallback;
8:
9: public MyEntityService()
10: {
11: Context=new MyEntityDomainContext();
12: Context.PropertyChanged += ContextPropertyChanged;
13: }
14:
15: private void ContextPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
16: {
17: if (NotifyHasChanges != null)
18: {
19: NotifyHasChanges(this, new HasChangesEventArgs() {HasChanges = Context.HasChanges});
20: }
21: }
22:
23: public void GetMyEntitys(Action<ObservableCollection<MyEntity>> getMyEntityCallback)
24: {
25: _getMyEntityCallback = getMyEntityCallback;
26: _operation = Context.Load(Context.GetMyEntityOverviewQuery());
27: _operation.Completed += OnLoadMyEntityCompleted;
28: }
29:
30: private void OnLoadMyEntityCompleted(object sender, EventArgs e)
31: {
32: _operation.Completed -= OnLoadMyEntityCompleted;
33: var MyEntitysList = new EntityList<MyEntity>(Context.MyEntitys, _operation.Entities);
34: _getMyEntityCallback(MyEntitysList);
35: }
36: }
实现IDisposable接口释放内存:View,ViewModel,Service
当你创建一个View,会创建其ViewModel,ViewModel又会创建Service,所以当你关闭View的视图的时候,这些引用还在吗?会不会内存泄露呢?具体如何实现IDisposable接口,如何调用释放内存,请看我的另一篇文章。
总结
使用的时候把这个Service用依赖注入(构造注入/属性注入)到ViewModel即可。
其他的ViewModel可以重用Services,而且Services易于扩展、维护和测试。
顺便说一下,在Prism框架中,这个Services的概念用到的地方很多,通过ServiceLocator更强,所以一定要用的好。