Prism研究(for WPF & Silverlight)7.View Injection和View Discovery

Prism研究(for WPF & Silverlight)7.View Injection和View Discovery,第1张

概述  一切从这里开始。Prism 文档对于这两个概念的解释着实有些扯淡,甚至自相抵牾,还是不要看了,乖乖听额讲吧。     我们晓得,每个Module中,实现了IModule接口的Module类,都要实现该接口的Initialize方法,一方面要注册一些自定义的接口和实现了该接口的类,为接下来的依赖注入做准备;另一方面,就是为Region加载View并显示(初始化View)。     加载View的   一切从这里开始。Prism 文档对于这两个概念的解释着实有些扯淡,甚至自相抵牾,还是不要看了,乖乖听额讲吧。

    我们晓得,每个Module中,实现了IModule接口的Module类,都要实现该接口的Initialize方法,一方面要注册一些自定义的接口和实现了该接口的类,为接下来的依赖注入做准备;另一方面,就是为Region加载VIEw并显示(初始化VIEw)。

    加载VIEw的方式,分为VIEw InjectionVIEw discovery两类,各有千秋。

1.       VIEw Injection,指的是RegionManager,它的属性Regions,这是一个集合类RegionCollection,同时还实现了基于Regionname的内部索引。于是,我们可以这样编写代码:

    VIEw-first:

this.regionManager.Regions["MainRegion"].Add(new HelloWorldVIEw());

    Presenter-first:

this.regionManager.Regions["MainRegion"].Add(this.container.Resolve<HelloWorldPresenter>().VIEw);

    有关VIEw-firstPresenter-first的概念,我们在下一节中专门介绍。

    VIEw Injection的视图如下,有点像中介者模式吧,那个Registry就是一个Mediator


   
    注意,VIEw Injection只适用于RegionManager,不适用于RegionVIEwRegistry,原因么,看我下面的分析。

2.       VIEw discovery,指的是RegionVIEwRegistryRegisterVIEwWithRegion方法,有2个重载:

        public voID RegisterVIEwWithRegion(string regionname,Type vIEwType)

        {

            this.RegisterVIEwWithRegion(regionname,() => this.CreateInstance(vIEwType));

        }

 

        public voID RegisterVIEwWithRegion(string regionname,Func<object> getContentDelegate)

        {

            this.registeredContent.Add(regionname,getContentDelegate);

            this.OnContentRegistered(new VIEwRegisteredEventArgs(regionname,getContentDelegate));

        }

 

    我们看到,第1个方法是基于第2个方法的,就是把Regionname和一个delegate(用于创建VIEw的一个实例)同时注册到字典ListDictionary<string,Func<object>>和委托链WeakDelegatesManager中。

    于是我们可以这样编写代码:

    VIEw-first:

            this. RegionVIEwRegistry.RegisterVIEwWithRegion("MainRegion",typeof(VIEws.HelloWorldVIEw));

    Presenter-first:

           this. RegionVIEwRegistry.RegisterVIEwWithRegion("MainRegion",

() => this.container.Resolve<IHelloWorldPresenter>().VIEw);

 

    有关VIEw-firstPresenter-first的概念,我们在下一节中专门介绍。

    VIEw discovery的视图如下,看这个图让我想起了GOF中的注册工厂:



    Prism文档中P18说到,VIEw discovery适用于V-first,而VIEw Injection同时适用于V-firstP-first。这是不恰当的。看了我上面的分析和代码,就会发现VIEw discovery也有以P-first方式实现的,而且也是很常用的。

    VIEw InjectionVIEw discovery,本来就是2个不同类——RegionManagerRegionVIEwRegistry的不同实现方式,连存储结构都不同,前者是集合,后者是字典。相对而言,前者的实现更直接一些(来一个招呼一个),后者比较绕(先对号入座,然后再用到谁招呼谁)。

    存储结构的不同,使得二者在性能上有很大差异。RegionManagerRegions属性是一个集合,所以可以手动添加或移除Region中的VIEw(使用集合的AddRemove方法),尤其是移除功能,可以释放不再使用的内存。

    相对而言,RegionVIEwRegistry在内部使用字典来存储VIEw,它的RegisterVIEwWithRegion方法就是把VIEw添加到这个字典中,但是,由于这个字典是私有的,不对外暴露,所以我们无法使用它的Remove方法来移除VIEw。这是因为,我们存储到字典中的VIEw都是弱引用,再回顾一下:

            this. RegionVIEwRegistry.RegisterVIEwWithRegion("MainRegion",typeof(VIEws.HelloWorldVIEw));

    这里typeof(VIEws.HelloWorldVIEw)就是一个弱引用,我们知道,.NET会自动回收不再使用的内存,所以,理想情况下,不再使用这个VIEw时,该VIEw所占的内存就会被自动回收了。但是,自动回收内存在什么时候发生呢?没人知道。所以,系统越来越慢,就是因为RegionVIEwRegistry的这个方法导致的。

    既然不好用,那为什么还要设计出RegionVIEwRegistry呢?

    说起来话长了。这要从Prism的第1版说起。话说,那时Prism中只有VIEw Injection机制,也就是说,只有RegionManager类。后来,大家发现RegionManager类也有不好的地方,就是在嵌套Region的时候,每一级Region中都要写点Regions[“Regionname”].Add方法,而且还要care层次间的关系,是不是觉得很麻烦?而且Prism经常会报错说找不到Regionname,以致于抛出异常(关于这一点,请参见我的另一篇文章)。为了方便开发,p&p小组在Prism2版中提供了RegionVIEwRegistry类,及其RegisterVIEwWithRegion方法,于是我们可以在任何地方使用该方法,而不需要在各自的VIEw中编写相应的代码。但是,简单是要付出代价的,那就是性能,上文已经分析过。

    同时,Prism框架把RegisterVIEwWithRegion也作为扩展方法添加到了RegionManager类中,实际上还是调用RegionVIEwRegistry类的RegisterVIEwWithRegion方法。于是,形成了一个组合关系。

    本来设计思想是蛮好的,可以屏蔽RegionVIEwRegistry类,对ClIEnt而言,只有RegionManager类,它同时具有RegisterVIEwWithRegion方法和Regions[“Regionname”]属性(前者是弱引用方式,后者是强引用方式)。

    但是,不知是微软p & p的那个DPE大脑进水,在Prism文档和示例又同时使用了RegionVIEwRegistryRegisterVIEwWithRegion方法。这就违背了设计的初衷。于是,我们糊涂了,不知道什么时候该使用哪一个类的哪一个方法,甚至开始怀疑人生。

总结

以上是内存溢出为你收集整理的Prism研究(for WPF & Silverlight)7.View Injection和View Discovery全部内容,希望文章能够帮你解决Prism研究(for WPF & Silverlight)7.View Injection和View Discovery所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1008314.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-22
下一篇2022-05-22

发表评论

登录后才能评论

评论列表(0条)

    保存