我看prism的一点感受(三) 初始化模块

上一篇讲到了模块是如何下载,以及加载到宿主程序中.但是在下载之前,我们要指定模块的路径,以及模块的类型名,才能有效下载,以及加载.

 

在第一篇的UnityBootstrapper类的讲述中,我们提到了要继承这个类,并重载几个方法.

其中一个重载的方法就是

   protected override IModuleCatalog CreateModuleCatalog()

        {
                return  Microsoft.Practices.Prism.Modularity.ModuleCatalog.CreateFromXaml(
                
new  Uri(“模块名”, UriKind.Relative));
        }

 

这个方法里有一行代码,是调用ModuleCatalog.CreateFromXaml方法,这个方法的作用是读取模块配置文件里面的内容,并产生ModuleInfo对象或ModuleInfoGroup对象,并将这对象放入到MdouleCatalog类里.

  方法有两个参数,第一个参数我在第一篇里写错了,不应该是模块名”, 而应该是模块配置文件名”,这里做个纠正. 第二个参数是指第一参数给的文件路径Uri 写的是绝对路径或是相对路径.

  接下来我按配置文件种类和格式”-------à”ModuleInfoMduleInfoGroup”-àModuleCatalog这个顺序来讲

  

模块配置文件一般可以两种方式来写 , 一个是写在 silverlight 资源文件里 , 一个是写在 app.config 文件里 . 

        一般认为写在silverlight资源文件里比较好,这是一个以xaml为后缀的文件名.书写的格式如下:

      <prism:ModuleCatalog

     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:       prism="clr-namespace:Microsoft.Practices.Prism.Modularity;assembly=Microsoft.Practices.Prism">

    <prism:ModuleInfo Ref="RentCar.LocationService.xap"

                      ModuleName="RentCar.LocationService"

                      ModuleType="RentCar.LocationService.ModuleInit,RentCar.LocationService,Version=1.0.0.0"

                      InitializationMode="WhenAvailable" />

    </prism:ModuleCatalog> 

      首先以Modulearity:ModuleCatalog节点开头, Modulearity是命名空间名,这在文件的第四行可以看到定义, ModuleCatalog是根节点名.这个好象不能写错

接下来可以看里面有一个ModuleInfo节点, 这表示整个项目里只有一个模块要下载,其中属性Ref 是要下载的xap文件的路径.可以是相对路径也可以是绝对路径.

ModuleName是项目的名称.

    ModuleType 是一个由逗号分割的字符串组成,第一部分是指定加载模块后,要实例化的第一个类名.

                                                             第二部分指这个类的命名空间

                                            第三部分是模块的版本号(可不写)

                                                             第四部分是模块的文化语言代码(可不写)

                                                             第五部指模块的公匙标记(可不写)

    InitializationMode 是即时下载还是以后下载, 这个值在"WhenAvailable"”OnDemand”中二选一

  注:配置文件中还有其他的节点,比方moduleinfogroup , modulestate,依赖模块等等,这里就不介绍了,可以查阅Prism的帮助文档

  

App.config 文档格式如下 :

  …….  

    现在我们来看看CreateFromXaml方法是如何读取Xaml文件的. 

ExpandedBlockStart.gif
public   static  ModuleCatalog CreateFromXaml(Stream xamlStream)
        {
            
if  (xamlStream  ==   null )
            {
                
throw   new  ArgumentNullException( " xamlStream " );
            }

#if  SILVERLIGHT
            
string  xaml;
            
using  (System.IO.StreamReader reader  =   new  System.IO.StreamReader(xamlStream))
            {
                xaml 
=  reader.ReadToEnd();
            }
            
return  XamlReader.Load(xaml)  as  ModuleCatalog;
#else
            
return  XamlReader.Load(xamlStream)  as  ModuleCatalog;
#endif
        }

 

    这个方法里调用了Silverlight类库中XamlReader.Load方法.

    XamlReader.Load方法是分析格式良好的 XAML 片段并创建相应的 Silverlight 对象树,然后返回该对象树的根”.

    这是什么意思咧,XAML按照根节点,子节点,孙子节点等格式定义好,XamlReader.Load读取这个文件后,可以按这个格式产生一个对象树,也就是一个对象包含一个子对象,子对象又包含子对象这样的一个情况.

   那么在上面的代码里,XamlReader.Load方法读取了文件流后,产生了对象,并把根节点转换成ModuleCatalog对象.再把子节点ModuleInfo也生成一个对象,并放入到一个Itmes属性中,ItemsCollection类型的 .

      注意: 1. 看到这里我们应该明的了,MoudleCatalog其实就是包装一个集合类的,这个集类可以存入moduleInfo modulegroup两个类型的对象.

      有兴趣的同学可以看看items 这个属性是继承了什么接口,moduleInfomodulegroup又是继承了什么接口,从而使他们产生关联.

 

   注意:2. ModuleCatalog其实也可以不读xaml文件,而是直接调用AddModuleAddModuleGroup两个方法,moduleInfomoduleGroup两种类型加载到Items里面去

 

   注意3, 既然能将模块信息添加到ModuleCatalog类里去,当然也提供了从ModuleCatalog读取模块信息的方法,但是,,,但是,,,但是,,,没有提供从ModuleCatalog里的集合中删除模块信息的方法!!!!!!!!如果你愿意,是可以在源代码中去添加这个方法的.

 

 

我们综合前一篇文章,可以大致明白Prism中几个类的分工,ModuleCatalog是用来存储我们项目中所有要下载的模块相关信息(注意是模块相关信息,不是模块本身),ModuleManager,则从ModuleCatalog中读取这些信息,去下载指定的模块.

回过头来看看 ModuleManager 类中的

ExpandedBlockStart.gif
public   void  LoadModule( string  moduleName)
        {
            IEnumerable
< ModuleInfo >  module  =   this .moduleCatalog.Modules.Where(m  =>  m.ModuleName  ==  moduleName);
            
if  (module  ==   null   ||  module.Count()  !=   1 )
            {
                
throw   new  ModuleNotFoundException(moduleName,  string .Format(CultureInfo.CurrentCulture, Resources.ModuleNotFound, moduleName));
            }
            IEnumerable
< ModuleInfo >  modulesToLoad  =   this .moduleCatalog.CompleteListWithDependencies(module);

            
this .LoadModuleTypes(modulesToLoad);
        }

 

     LoadModule方法就是根据参数提供的模块名,这应该就是模块项目名称.moudleCatalog.Modules集合中找到对应的ModuleInfo,然后根据ModuleInfo类中的文件路径去下载了.

 

现在我们知道了Prism是怎么保存模块信息,以级怎么下载模块,加载模块到宿主进程.但是下载来的模块总要显示视图出来吧,那视图怎么显示咧????

通常我们在功能模块里总要写上这一个类

ExpandedBlockStart.gif
public   class  ModuleInit:IModule
    {

        
private   readonly  IUnityContainer container;
        
private   readonly  IRegionManager regionmanager;

        
public  ModuleInit(IUnityContainer container,IRegionManager regionmanager)
        {
            
this .container  =  container;
         
this .regionmanager  =  regionmanager;
        }

        
public   void  Initialize()
        {
  
this .regionmanager.RegisterViewWithRegion( " MainRegion " ,() => this .container.Resolve < ModulePage > ());         
  
        }
    }

 

这个类是每个模块必须要写的,它主要是告诉Prism框架,我把我下载后,把我的视图放在哪个区域里(关于区域Region,是下一篇要讲的内容)

 

现在讲讲这类里面的两个方法,一是构造函数,从外面接收一个依赖注入容器( 这个类从来没讲过,这里简单讲讲,它的作用就是帮我们实例化对象,不需要我们去new一个对象出来)

再就是接收一个区域管理器,这个区域管理器就是控制视图加载到区域里面 .

 

第二个函数名叫Initialize()这个函数名一定不能写错,一定要这样

这个函数的功能就是实例化一个模块中的视图

this.container.Resolve< ModulePage >()

然后把这个视图嵌入到“容器视图”的某个区域中去。这个打引号的容器视图就是我们在第一篇中讲到的MainPage视图,它是整个项目的主视图。其他功能模块的视图全嵌在这个视图里面。

嗯!!! 

这个类是怎么被调用的????

还是按步骤来。

第一步, 我们写个xaml的模块配置文件,这个文件中ModuleInfo节点有个属性ModuleType,还记得不???看上面!!!!!

这个ModuleType的值,第一段就写了

ModuleType="RentCar.LocationService.ModuleInit

这是Prism框架下载模块后,第一个要实例化的类。

第二步,由ModuleCatalog去读这个文件,把ModuleInfo节点转化成对象存储在集合里

第三步,由ModuleManager读取ModuleCatalog中的信息,去下载模块。

下载完了干什么???当然要实例化 ModuleInit 类,然后去调用

public void Initialize()

        {

         this.regionmanager.RegisterViewWithRegion("MainRegion",()=>this.container.Resolve<ModulePage>());         

         } 

      方法,加载视图到区域。

那这个活由谁来干??

ModuleInitializer 类。

一起来看看ModuleManger.LoadModuleTypes是怎么干的。

  代码

 

该方法在循环中调用this.BeginRetrievingModule(moduleInfo);去下载模块。

在这个方法的最后一行this.LoadModulesThatAreReadyForLoad() 方法里就是去实例化ModuleInit类了。

     protected void LoadModulesThatAreReadyForLoad()

        {

            bool keepLoading = true;

            while (keepLoading)

            {

                keepLoading = false;

                IEnumerable<ModuleInfo> availableModules = this.moduleCatalog.Modules.Where(m => m.State == ModuleState.ReadyForInitialization);

 

                foreach (ModuleInfo moduleInfo in availableModules)

                {

                    if ((moduleInfo.State != ModuleState.Initialized) &&  (this.AreDependenciesLoaded(moduleInfo)))

                    {

                        moduleInfo.State = ModuleState.Initializing;

                        this.InitializeModule(moduleInfo);

                        keepLoading = true;

                        break;

                    }

                }

            }

        }        

 这个方法是在下载模块以后,找出没有初始化模块,对其初始化。

this.InitializeModule(moduleInfo); 这是倒数第三行代码。

 

      private void InitializeModule(ModuleInfo moduleInfo)

        {

            if (moduleInfo.State == ModuleState.Initializing)

            {

                this.moduleInitializer.Initialize(moduleInfo);

                moduleInfo.State = ModuleState.Initialized;

                this.RaiseLoadModuleCompleted(moduleInfo, null);

            }

        }

 

看到标成红色的代码没有,这个this.moduleInitalizer 就是ModuleInitializer 类的实例

      moduleInitalizer. Initialize(moduleInfo) 方法就是从 moduleInfo 中取出 ModuleType 类型名,然后用反射去实例化 ModuleInit 类,再调用 ModuleInit. Initialize() 方法,实例化模块视图,将视图添加到区域中 

转载于:https://www.cnblogs.com/jasson/archive/2010/11/29/1891293.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值