动态加载的Assembly通过AppDomain进行卸载

[ At 6/18/2009 By wukong   9 comments ]

我前天写的一篇文章《c#获取程序集信息》中,描述了如何实用System.Reflection下Assembly类对程序集进行动态的加载、获取信息并调用其中的类和方法,但Assembly只提供了加载,并没提供卸载方法。

这时由于.net的应用程序域的底层实现机制所致,更细节的技术特性这里就不叙述了,本文就先说一下简单的原因,并给出一个解决的方法。

Assembly只能动态加载,不提供卸载方法,如果想卸载一个Assembly实例,只能是通过卸载这个Assembly所在的容器,就是他所在的应用域AppDomain。每个运行中的程序集实例都有一个AppDomain,可以看作将相关的程序集都放到这个域的容器里运行一样。那么,动态加载的Assembly程序集实例,不能直接卸载,要卸载他的应用域,但默认是加载到主程序集本身的应用域appdomain中了,只能通过关闭程序来卸载,哈哈,这当然不是我们想要的。

好在.net允许动态的创建另外一个容器Appdomain,这样就可以通过新建一个appdomain,在这个新建的域里加载要动态加在的程序集,然后调用其中的程序集,不需要的时候、需要卸载的时候,就可以将这个临时创建的appdomain卸载,从而达到动态加载和卸载assembly的效果。

实现代码如下:

 
  1. //测试的类,注意这里的MarshalByRefObject,有了这个,这个类才能在远程跨域调用中序列化传送,从而不发生访问异常。
  2. public class ModuleManage : MarshalByRefObject
  3. {
  4.     public void GetDesc(string filename,ref string desc)
  5.     {
  6.         //首先为创建appdomain做准备,创建一个appdomainsetup,此实例包含了后面创建appdomain所需的一些参数
  7.         AppDomainSetup setup = new AppDomainSetup();
  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.         //创建应用域appdomian
  15.       AppDomain appDomain = AppDomain.CreateDomain("TestDomain"null, setup);
  16.       //在新建的应用域中创建本程序集本身的实例,呵呵,就是本程序集在此加载一份
  17.       string aname = Assembly.GetExecutingAssembly().GetName().FullName;
  18.       string tname = this.GetType().FullName;  
  19.       object m = appDomain.CreateInstanceAndUnwrap(
  20.           aname, tname);
  21.       //调用在临时域中运行的本类的方法_GetDesc,该方法实现了加载和获取一个程序集的描述信息
  22.       desc = ((ModuleManage)m)._GetDesc(filename);
  23.       //最后使用完毕了,就卸载临时域,这样动态动态创建的域、另一个本类的实例、动态加载的那个assembly,都被卸载
  24.       AppDomain.Unload(appDomain);
  25.     }
  26.     
  27.     //此方法在临时创佳的域中创建本类实例并进行调用,最终将随着临时域卸载而销毁。
  28.     public string _GetDesc(string filename)
  29.     {
  30.         Assembly a = Assembly.LoadFile(filename);
  31.         return ((AssemblyDescriptionAttribute)Attribute.GetCustomAttribute(a, typeof(AssemblyDescriptionAttribute))).Description;
  32.     }
  33. }

上面的代码描述的类,仅仅是我测试所写,实现了动态加载一个程序集并获取该程序集的描述信息,并且动态的卸载,从而不会造成该程序集的dll文件被锁定。代码中的注释已经描述的足够详细,有兴趣的可以认真看下注释。

« 超强自制电脑桌试用命令查看域名解析服务器 »
  • 相关文章:
  • 3.gsdf
  • 不应使用 Assembly.LoadFile(),
    应使用 Assembly.LoadFrom(),
    这样不用下AppDomain.Unload(appDomain),dll也不会被锁定。
  • 9/20/2009 5:22:42 AM 回复该留言
  • 4.wukong
  • Adore是么,可我的记得当时测试时总是被锁定,才搞了这么个方法,呵呵,回头再写段代码试试看。
  • 9/21/2009 9:56:24 AM 回复该留言
  • 7.萧亦然
  • 不应使用 Assembly.LoadFile(),
    应使用 Assembly.LoadFrom(),
    这样不用下AppDomain.Unload(appDomain),dll也不会被锁定。
    是不是这样的啊?
  • 6/21/2010 5:02:35 PM 回复该留言
  • 9.wukong
  • 支持楼上,c#就是给我这样的垃圾用的,没办法,俺没文化。
  • 12/6/2010 10:10:00 AM 回复该留言

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By 空空如也 

Copyright 167-2009 www.7es.cn . Some Rights Reserved. Email:iamwgh@msn.com QQ:49556
Friends site:Null