KK的技术人生

技术改变世界
SL2 动态加载程序集---OnDemand模式

随着我们开发的进行,我们的SL生产出来的Xap包可能会越来越大,这个时候我们可能会考虑将某些功能集独立到某个程序集中,放置在SL可以访问的路径下,然后在需要的时候动态去加载这个程序集。关于这方面的例子网上也有不少,但大多是告诉你在下载dll之后通过反射来实例化类型。我们知道反射是一种比较慢的操作,对于这里我们使用的程序集,其实内部有什么类我们都是知道的,那么有没有一种办法可以即获得动态加载程序集的好处,又不用付出反射的代码呢?答案是有的。下面我通过一个简单的Demo来演示一下怎么实现。

首先还是如下图一样建立三个工程:

其中Extension是我们独立出来的程序集,需要动态加载的,里面我们只设置了一个非常简单的Ext类,这个Ext类只有一个静态的Encrypt方法,用来加密字符串的。下面两个工程分别是我们的主SL应用程序和测试网站。

我们的主SL程序非常简单,界面如下

输入一个任意字符串,然后点击加密就会调用Ext的静态加密方法,并弹出加密之后的字符串给用户。

好,让我们先按照传统的思路来做。

由于这个独立程序集是我们已知的,所以我们可以直接添加引用到主SL工程中。(这里为什么我要强调"已知"这个概念呢?因为只有对于我们未知的可能实现了某些契约了的程序集,我们一般会通过LoadAssembly的方法而不是直接添加引用的方式来加载)

在这里需要注意一点,当我们添加完引用之后,我们需要设置其CopyLocal的属性

这样该dll不会被自动打包到Xap包中,否则就没意义了。

OK,到现在为止,我们所做的都是一些标准的DotNet特性的东西。接下来的部分比较有意思了。

我们绑定加密按钮的Click事件,并在处理函数里面加入如下代码:

  

我们定义了一个标识变量_assemblyLoaded来指示当前使用的加密程序集是否已经成功加载了。如果是的话,则直接执行ShowEncryptedText。否则我们加载程序集。为了在加载之后能够自动继续执行一致的逻辑,在这里我使用了后台线程对象BackgroundWorker,不断轮询程序集是否成功加载了,直到加载成功为止。然后我们通过UserControlDispatcher对象来异步调用加密逻辑。这里如果直接调用ShowEncryptedText会抛出线程访问错误,原因不详

我们先来看一下加载程序集的逻辑。

  

这段代码比较简单,不做太多解释。

我们再来看一下,我们的ShowEncryptedText函数的实现

  

很简洁的代码,我们仅仅使用MessageBox来显示加密过后的字符串。在这里Ext.Encrypt方法是来自我们刚刚加载成功的外部程序集。

这里有一个问题,为什么我们要把这么短的代码放到一个专门的函数里头呢?为什么不在OnEncrypt事件处理函数中就直接调用呢?这其实是先有鸡还是先有蛋的问题了(*^__^*) DotNet在进入一个方法的时候,会预先查找函数里面使用到的所有方法所在的程序集,因此如果我们直接调用Ext的方法,那么,啊,哈,我不说你也知道了吧。(这个特性在Javascript中也有,JS在执行到一个函数时,会预先找出函数内使用的所有变量,所以不论你在函数内部哪个地方声明的变量,都是一样的效果)

也就是因为上面这个原因,所以在方法上面要加上NoInlining编译属性,是为了防止编译器自作聪明把短函数内联了导致异常。

希望此文能帮到你~

  

image

posted on 2008-11-10 01:48  KK2038  阅读(1283)  评论(0编辑  收藏  举报