AppDomain与Assembly的动态加载与卸载

为了将问题描述清楚,我们先来看一个例子。在这个例子中,WinForm上有一个按钮,当用户点击这个按钮后,就会装载一个已经存在的Assembly,并且在界面的Label控件上显示出这个Assembly的FullName。对Reflection稍微熟悉一点的朋友都知道,这是非常简单的事情,只需要用Assembly.LoadFile方法获得Assembly,然后用FullName属性来显示即可,比如下面的代码:

  1. privatevoidbutton1_Click(objectsender,EventArgse)
  2. {
  3. Assemblyassembly=Assembly.LoadFile(@"C:\testlib.dll");
  4. label1.Text=assembly.FullName;
  5. }

当然,程序执行正常,您不会发现任何编译时或运行时的错误。然而,当你在没有退出此程序之前,再去编译被调用的testlib.dll,你会发现,Visual Studio无法完成编译,提示说该文件正在被其它的进程所使用。

事实上,我们的程序与这个testlib.dll并没有太大的关联,我们的程序只不过就是显示一下testlib.dll的基本信息。如果testlib.dll是一个共享的库,那么资源独占问题会影响到其它程序的正常工作。

Assembly没有Unload的功能,但可以使用AppDomain来解决这个问题。基本思路是,创建一个新的AppDomain,在这个新建的AppDomain中装载assembly,调用其中的方法,然后将获得的结果返回。在完成所有操作以后,调用AppDomain.Unload方法卸载这个新建的AppDomain,这样也同时卸载了assembly。注意:你无法将装载的assembly直接返回到当前应用程序域(AppDomain)。

首先,创建一个RemoteLoader,这个RemoteLoader用于在新建的AppDomain中装载assembly,并向外公布一个属性,以便外界能够获得assembly的FullName。RemoteLoader需要继承于MarshalByRefObject。代码如下:

  1. publicclassRemoteLoader:MarshalByRefObject
  2. {
  3. privateAssemblyassembly;
  4. publicvoidLoadAssembly(stringfullName)
  5. {
  6. assembly=Assembly.LoadFrom(fullName);
  7. }
  8. publicstringFullName
  9. {
  10. get{returnassembly.FullName;}
  11. }
  12. }

其次,创建一个LocalLoader。LocalLoader的功能是创建新的AppDomain,然后在这个新的AppDomain中调用RemoteLoader,以便通过RemoteLoader来创建assembly并获得assembly的相关信息。此时被调用的assembly自然被装载于新的AppDomain中。最后,LocalLoader还需要提供一个新的方法,就是AppDomain的卸载。代码如下:

  1. publicclassLocalLoader
  2. {
  3. privateAppDomainappDomain;
  4. privateRemoteLoaderremoteLoader;
  5. publicLocalLoader()
  6. {
  7. AppDomainSetupsetup=newAppDomainSetup();
  8. setup.ApplicationName="Test";
  9. setup.ApplicationBase=AppDomain.CurrentDomain.BaseDirectory;
  10. setup.PrivateBinPath=Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"private");
  11. setup.CachePath=setup.ApplicationBase;
  12. setup.ShadowCopyFiles="true";
  13. setup.ShadowCopyDirectories=setup.ApplicationBase;
  14. appDomain=AppDomain.CreateDomain("TestDomain",null,setup);
  15. stringname=Assembly.GetExecutingAssembly().GetName().FullName;
  16. remoteLoader=(RemoteLoader)appDomain.CreateInstanceAndUnwrap(
  17. name,
  18. typeof(RemoteLoader).FullName);
  19. }
  20. publicvoidLoadAssembly(stringfullName)
  21. {
  22. remoteLoader.LoadAssembly(fullName);
  23. }
  24. publicvoidUnload()
  25. {
  26. AppDomain.Unload(appDomain);
  27. appDomain=null;
  28. }
  29. publicstringFullName
  30. {
  31. get
  32. {
  33. returnremoteLoader.FullName;
  34. }
  35. }
  36. }

最后,修改我们WinForm上的Button Click事件处理过程,改为如下的形式:

  1. privatevoidbutton1_Click(objectsender,EventArgse)
  2. {
  3. LocalLoaderll=newLocalLoader();
  4. ll.LoadAssembly(@"C:\testlib.dll");
  5. label1.Text=ll.FullName;
  6. ll.Unload();
  7. }

在完成上述的修改后,我们的程序也同样能够正确地显示assembly的FullName,而且,在显示完assembly信息后,程序会主动卸载新建的AppDomain,以防止testlib.dll的资源独占,影响其它程序的运行。

参考:http://www.microsoft.com/china/msdn/library/langtool/vcsharp/csharp05162002.mspx?mfr=true

时间: 2024-10-24 06:47:26

AppDomain与Assembly的动态加载与卸载的相关文章

AppDomain与Assembly的动态加载与卸载简介

为了将问题描述清楚,我们先来看一个例子.在这个例子中,WinForm上有一个按钮,当用户点击这个按钮后,就会装载一个已经存在的Assembly,并且在界面的Label控件上显示出这个Assembly的FullName.对Reflection稍微熟悉一点的朋友都知道,这是非常简单的事情,只需要用Assembly.LoadFile方法获得Assembly,然后用FullName属性来显示即可,比如下面的代码: private void button1_Click(object sender, Eve

c# 动态加载和卸载C#DLL程序集 C++程序集,

c# 动态加载和卸载C#DLL程序集的原文链接是: http://www.cnblogs.com/MiracleLee/archive/2013/01/31/2886323.html 做一个开源项目地址是: 点击打开链接

linux下驱动模块化编译,动态加载以及卸载

步骤:: 1.编写first_driver_hello.c文件,将其放在/linux2.6.32/drivers/char路径下: 2.在/linux2.6.32/drivers/cha/Kconfig文件中添加如下语句:   3.在/linux2.6.32/drivers/cha/Makefile文件中添加如下语句:   4.编译模块:          在控制台中进入到/linux2.6.32目录          Make  ARCH=arm  CROSS_COMPILE=arm-none

构建插件式的应用程序框架(三)-动态加载

不管你采用什么方式实现插件式的应用程序框架,核心还是动态加载,换句话说,没有动态加载技术也就无所谓插件式的应用程序框架了.使用Com实现的话,你可以利用Com的API通过ProgID来动态创建COM对象,如果使用普通DLL,你需要使用Windows 的API函数LoadLibrary来动态加载DLL,并用GetProcAddress函数来获取函数的地址.而使用.NET技术的话,你需要使用Assembly类的几个静态的Load(Load,LoadFile,LoadFrom)方法来动态加载汇集. 一

.NET 动态加载程序集 (三)

我们先看看一般的反射的动态方法查找 下面为ms自带的例子ms-help://MS.VSCC/MS.MSDNVS.2052/cpref/html/frlrfsystemreflectionmethodbaseclassinvoketopic.htm public class A {    public virtual int method () {return 0;} } public class B {    public virtual int method () {return 1;} }

动态加载用户控件的组件

动态|加载|控件 动态加载用户控件的组件!(终结MasterPages技术) 让我们来做个页面模版吧!有了模版是不是就可以统一了呢!Sure ! 比如:模版页Template.ascx中我们留出中间一个部分,或者你想要留出的一个空间,让以后放入你想要的内容. 好了!那么在我们的页面index.aspx上我们就可以引用这个Template.ascx,然后在空出的部分放入我们特别的东西,当然最好是在空的地方我们插入另外一个页面如:List.ascx, 当然我们在做个页面MyArchive.aspx.

动态加载类的原理——元数据的使用

动态|加载|数据 在使用.NET创建的程序或组件时,元数据(metadata)和代码(code)都存储于"自成一体"的单元中,这个单元称为装配件.我们可以在程序运行期间访问这些信息. 在System.Reflection中有这样一个class----Assembly,我们可以通过它来加载一个装配件.方法如下: Assembly assm=Assembly.LoadFrom(fileName); 其中filename是要加载的装配件的文件名称(带路径). 接下来,我们就可以通过使用Sys

如何动态加载控件以及插件编程思想(C#)

编程|动态|加载|控件 关键词:动态加载,控件,插件 控件,在实现快速开发中起着非常重要的作用,它可以将某一特定功能封装起来,供可户程序员调用,更重要的是它还可以实现插件式开发,使软件的灵活性.可扩充性大大增强.在网络上,也有很多动态加载控件.动态调用类成员等的资料.下面,我就将动态加载控件总结一下,以供大家参考.(不过由于本人水平有限,不一定有参考价值,写出来一方面是为了总结自己,以求提高,另一方面也希望各为朋友看到我的不足,给我提出宝贵意见)一.动态加载控件 动态加载,最基本用到的就是反射机

Visual Basic .NET 中动态加载类 (二)

visual|动态|加载 Microsoft 步骤 3:创建配置文件以存放可用窗体 应用程序在运行时需要的某些信息可能在编译时无法提供,这些信息通常放置在配置文件中.在 Visual Basic 6.0 中,配置文件应该是 INI 文件或 Windows 注册表.而在 .NET 中,则使用基于 XML 的配置文件. 我们无法详细介绍配置文件,因为这个主题非常复杂.但是,您应该知道,Windows 窗体应用程序的配置文件与应用程序的 EXE 启动文件在同一个目录中.配置文件的名称与程序的 EXE