Unity应用架构设计(5)——ViewModel之间如何共享数据

对于客户端应用程序而言,单页应用程序(Single Page Application)是最多见的表现形式。有经验的开发人员每每会把一个View分解多个SubView。那么,如何在多个SubView之间 『共享数据』 是一个很棘手的事情。又由于ViewModel才是真正为View提供数据来源,因此本质上『共享数据』指的是多个ViewModel之间共享同一块数据控件。javascript

JavaScript中的原型链

谈到『共享』两字,脑海里跳出第一个印象就是『继承』。对吧,由于你是父母的孩子,因此理所固然你能够和父母共享家中的一切。因此『共享』的前提,就是构建一个『继承链』,也就是JavaScript中的『原型链』。java

那么JavaScript是怎样实现原型链呢?有经验的JavaScript程序员想必早就记的倒背如流了——经过内置属性 __proto__ 来实现。git

因此ViewModel之间『共享数据』的核心就是如何去实现一个继承链,以下所示:程序员

为ViewModel构建继承关系

有了上述的分析以后,只要仿照JavaScript的 __proto__ 的实现,咱们对全部ViewModel的基类ViewModelBase添加一个ParentViewModel 属性,它表明当前ViewModel的父亲对象。github

public class ViewModelBase
{
    public ViewModelBase ParentViewModel { get; set; }
    //...
}复制代码

接着我参考了WPF中是怎样获取父ViewModel当中的数据:this

Binding="{Binding RelativeSource={RelativeSource FindAncestor, 
 AncestorType={x:Type Window}}, Path=DataContext.ParentViewModelProperty}复制代码

能够看到经过 FindAncestor 方法,去指定 AncestorType 类型的上层对象中获取数据。spa

因此,我为ViewModelBase 增长一个扩展方法,能够经过继承链实现从指定的祖先对象获取数据。code

public static IEnumerable<T> Ancestors<T>(this ViewModelBase origin) where T : ViewModelBase
{
    if (origin==null)
    {
        yield break;
    }
    var parentViewModel = origin.ParentViewModel;
    while (parentViewModel!=null)
    {
        var castedViewModel = parentViewModel as T;
        if (castedViewModel != null)
        {
            yield return castedViewModel;
        }
        parentViewModel = parentViewModel.ParentViewModel;
    }
}复制代码

对应在ViewModel中,能够经过 Ancestors扩展方法获取上层对象的数据cdn

var ancestors = this.Ancestors<FaceBoxViewModel>();复制代码

最后,以图示的形式会更加直观,下图所示,SubViewModel依靠继承链能够轻松访问到ParentViewModel的共享数据:xml

小结

本篇文章介绍了怎样在ViewModel之间共享数据,实际上解决方案是很是简单的,人为的构造了一个继承链并随着继承链往上找,老是能找到但愿获取到的数据。相似与JavaScript中的原型链,维护了一种至上而下的父子关系。
源代码托管在Github上,点击此了解

欢迎关注个人公众号:

相关文章
相关标签/搜索