查看文章 |
演示地址: http://silverlight.services.live.com/invoke/112026/AliqiSilverlight/iframe.html Silverlight的应用中,比起使用webservice,通常有一种更好的解决方案来处理程序模块化的问题,即动态加载其他XAP包,并应用到主应用程序上。 本文讨论的就是这种实现,在主XAP里动态地加载其他XAP,并应用资源,实例化,展现。 先来说说核心,如何将其他模块读取到客户端的主XAP里,这一步通常是由WebClient来负责实现的。 简而言之是 webClient.OpenReadAsync(uri); 然后去捕捉OpenReadCompletedEventHandler事件。 当该事件触发完成,如果没有异常的话,[OpenReadCompletedEventArgs e]中存放的Result就是所需的Stream,也就是你需要加载的XAP。 然后你需要的就是去解析这个XAP包,然后将获取的资源文件Merge到App的Resource中,代码如下: App.Current.Resources.MergedDictionaries.Add(resDict); 当这个顺序做下来,那么接着再去反射相关的Page、UserControl等等控件时,它们所对应的StaticResource将会在App.Current.Resources中找到。于是便会成功实例化。但是请确保该资源文件的生成操作设置为Content(内容),否则相对URI无法找到。 具体使用方法,在你主应用程序中这样调用: public partial class MainPage : UserControl public MainPage() moduleLoader.Loaded = new ModuleLoadedCompleted(LoadResource); private void LoadResource(Stream stream) moduleLoader.Close();
效果图:
看到很多人都在讨论动态加载XAP的问题,aliqi决定再深入一下,对于减小XAP的大小,提出一个解决方案: 如果你使用silverlight3是以下这种情况的话,请留意: 一个主XAP在运行的过程中动态地请求加载其他XAP,并且这些子XAP也可能继续请求其他的XAP,这是我们需要讨论的情况。 简单来说主XAP中已经加载的DLL在子XAP中无需再去加载,某个子XAP中先加载过的,若其他XAP里也用到了,那么也无需加载即可使用,这个原因是AssemblyPart.Load方法,可以自己深入一下。总的来说,只要已经加载过的DLL,那么遇到重复的完全可以不加载就可以使用。 明白了这个原理,那么请对你的所有的silverlight-application进行reduce设置:
在每个子XAP的References里,你需要仔细检查一下,哪些DLL是主XAP已经添加了的。找到它们,并将它们的属性[复制到本地]设置为false
Code Src:http://code.google.com/p/aliqisilverlight/ 请从SVN取出就可以了,暂不提供下载包。 具体的原理,我懒得解释了,诸位看官请自行研究。下面到废话了: 本文版权属aliqi所有,若需引用此文章,请保留该部分以使文章完整,谢谢。代码可任意修改、分发,但请保留头部的注释部分,以表示对各位劳动成果的尊重。 |





