你的分享就是我们的动力 ---﹥

Prism2.0之自定义ModuleCatalog(for Silverlight)

时间:2012-07-26 12:41来源:www.chengxuyuans.com 点击:

前段时间碰到有人问我,在Prism中,可否把模块信息放到xml文件中。这个自然没有问题,我们做一个自己的ModuleCatalog就好,不 过我一直没有做,今天正好简单实现了一下,有兴趣的朋友可以参考。

为什么要分模块,这个当然有很多好处,比如独立开发、独立测试,独立加载,而且模块之间没有直接引用,修改之后不会引起其他模 块产生问题,总归好处多多。当我们做一个小型的Silverlight程序时,可以不用考虑Prism,直接做就好了,但是如果你做一个RIA,比如 business application,那么可能会有上百个页面,不同的数据、表格等等,如果不分模块,那最后肯定就乱成一锅粥了。架构就是为了 让我们的项目更加有条理,并且在变的越来越复杂时能够更好的控制,还能随时适应变化的要求。

Prism2.0中,本身可以把模块的配置信息放置到XAML中,在自带的smaple中,我们可以看到如下代码:

1 <Modularity:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3                  xmlns:sys="clr-namespace:System;assembly=mscorlib"
4                xmlns:Modularity="clr- namespace:Microsoft.Practices.Composite.Modularity;assembly=Microsoft.Practices.Composite">
5      <Modularity:ModuleInfoGroup Ref="ModuleX.xap" InitializationMode="OnDemand">
6          <Modularity:ModuleInfo ModuleName="ModuleX" ModuleType="ModuleX.ModuleX, ModuleX, Version=1.0.0.0" />
7      </Modularity:ModuleInfoGroup>
8     <Modularity:ModuleInfoGroup Ref="ModulesWY.xap"  InitializationMode="WhenAvailable">
9         <Modularity:ModuleInfo ModuleName="ModuleY"  ModuleType="ModuleY.ModuleY, ModulesWY, Version=1.0.0.0">
10              <Modularity:ModuleInfo.DependsOn>
11                  <sys:String>ModuleW</sys:String>
12              </Modularity:ModuleInfo.DependsOn>
13         </Modularity:ModuleInfo>
14          <Modularity:ModuleInfo ModuleName="ModuleW" ModuleType="ModuleW.ModuleW, ModulesWY, Version=1.0.0.0">
15          </Modularity:ModuleInfo>
16     </Modularity:ModuleInfoGroup>
17     <!--  Module info without a group -->
18     <Modularity:ModuleInfo Ref="ModuleZ.xap" ModuleName="ModuleZ"  ModuleType="ModuleZ.ModuleZ, ModuleZ, Version=1.0.0.0" />
19 </Modularity:ModuleCatalog>

在Bootstrapper中,我们就可以如下调用:

protected override IModuleCatalog GetModuleCatalog()
{
return
ModuleCatalog.CreateFromXaml(
new  Uri("/RemoteModuleLoading;component/ModulesCatalog.xaml", UriKind.Relative));
}

如果我们要放在XML中,也很简单,声明如下的这么一个文件:

<?xml version="1.0" encoding="utf-8" ?>
<Modules>
<Module name="LeftMenuModule"  mode="WhenAvailable" type="SilverlightMonitorApplication.LeftMenuModule.LeftMenuModule, SilverlightMonitorApplication,  Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Module name="BottomMenuModule" mode="OnDemand"  type="SilverlightMonitorApplication.BottomMenuModule.BottomMenuModule, SilverlightMonitorApplication,  Version=1.0.0.0, Culture=neutral,  PublicKeyToken=null">
<Module.DependsOn>
<ModuleName>LeftMenuModule</ModuleName>
<Module Name>Module1</ModuleName>
</Module.DependsOn>
</Module>
<Module name="Module1"  mode="OnDemand" type="SilverlightMonitorApplication.Module1.Module1, SilverlightMonitorApplication, Version=1.0.0.0,  Culture=neutral, PublicKeyToken=null">
</Module>
<Module name="Module2" mode="OnDemand"  type="SilverlightMonitorApplication.Module2.Module2, SilverlightMonitorApplication, Version=1.0.0.0, Culture=neutral,  PublicKeyToken=null">
</Module>
</Modules>

然后自己实现一个ModuleCatalog,我这里就命名为XmlModuleCatalog,这个XmlModuleCatalog当然要从 ModuleCatalog继承下来。当 然你也可以有更好的实现方式。我就提供个思路就好,代码我随手写的,论写代码,我是赶不上专职开发人员了。

public class XmlModuleCatalog : ModuleCatalog
{
public XmlModuleCatalog(string xmlUri)
: base()
{
try
{
XElement doc = XElement.Load(xmlUri);
var q = from x in doc.Descendants("Module")
select new ModuleInfo(x.Attribute("name").Value, x.Attribute("type").Value, (from c in x.Descendants ("ModuleName")
select c.Value).ToArray()
) { InitializationMode = x.Attribute("mode").Value.Equals("OnDemand")  ? InitializationMode.OnDemand : InitializationMode.WhenAvailable };
foreach (ModuleInfo m in q)
{
this.AddModule(m);
}
}
catch
{
throw new ArgumentException("XML file is not found or  invalid!");
}
}
}

然后就可以在bootstrapper里面轻易调用

protected override IModuleCatalog  GetModuleCatalog()
{
try
{
return new XmlModuleCatalog ("ModuleInfo.xml");
}
catch
{
return null;
}
}

这里注意几点:

1. XML文件的BuildAction为Content,不需要当做资源编译到dll中。

2. 我没有去考虑每个模块在不同xap里面的情况,因为这种情况直接用xaml来描述就好了,没必要再自己重新做。

3. Depends的问题,只要放在ModuleName里面就好了,我并没有去管ModuleName是否放在<Module.DependsOn>里面,当然主要是 图省事。

4. 我使用LINQ来实现的,这样比较省事一点,大家也可以用其它的方式来读取XML。

这里说下模块按需下载的问题,如果模块需要按需下载,直接用XAML的形式就好了,这个Prism里面是自带的,不过考虑一般项目的模 块不是特别多,而每个模块不是特别大,经常每个模块几十K,100多K,所以都打包在一起更加方便。当然如果模块过多或者过大,还是应 该采用按需下载的方式比较好。

在Prism中,模块的加载过程和那一大堆class啊,interface啊之间的关系,可以从下面两个图中来了解:

上面两个图取自Prism的帮助文档中。

当然其实我定义这个xml文件,最初的初衷是想把module的view信息定义进去,让view也能根据配置文件动态加载。这个 XmlModuleCatalog应该说是一个附属品。

转载注明地址:http://www.chengxuyuans.com/slverlight/42358.html