博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
转,AppDomain与Assembly的动态加载与卸载
阅读量:4663 次
发布时间:2019-06-09

本文共 2884 字,大约阅读时间需要 9 分钟。

自,

 

 

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

private void button1_Click(object sender, EventArgs e)  

{  
    Assembly assembly = Assembly.LoadFile(@"C:\testlib.dll");  
    label1.Text = assembly.FullName;  
}  
当然,程序执行正常,您不会发现任何编译时或运行时的错误。然而,当你在没有退出此程序之前,再去编译被调用的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。代码如下:

public class RemoteLoader : MarshalByRefObject  

{  
    private Assembly assembly;  
  
    public void LoadAssembly(string fullName)  
    {  
        assembly = Assembly.LoadFrom(fullName);  
    }  
  
    public string FullName  
    {  
        get { return assembly.FullName; }  
    }  
}  
其次,创建一个LocalLoader。LocalLoader的功能是创建新的AppDomain,然后在这个新的AppDomain中调用RemoteLoader,以便通过RemoteLoader来创建assembly并获得assembly的相关信息。此时被调用的assembly自然被装载于新的AppDomain中。最后,LocalLoader还需要提供一个新的方法,就是AppDomain的卸载。代码如下:

public class LocalLoader  

{  
    private AppDomain appDomain;  
    private RemoteLoader remoteLoader;  
  
    public LocalLoader()  
    {  
        AppDomainSetup setup = new AppDomainSetup();  
        setup.ApplicationName = "Test";  
        setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;  
        setup.PrivateBinPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "private");  
        setup.CachePath = setup.ApplicationBase;  
        setup.ShadowCopyFiles = "true";  
        setup.ShadowCopyDirectories = setup.ApplicationBase;  
  
        appDomain = AppDomain.CreateDomain("TestDomain", null, setup);  
        string name = Assembly.GetExecutingAssembly().GetName().FullName;  
        remoteLoader = (RemoteLoader)appDomain.CreateInstanceAndUnwrap(  
            name,  
            typeof(RemoteLoader).FullName);  
    }  
  
    public void LoadAssembly(string fullName)  
    {  
        remoteLoader.LoadAssembly(fullName);  
    }  
  
    public void Unload()  
    {  
        AppDomain.Unload(appDomain);  
        appDomain = null;  
    }  
  
    public string FullName  
    {  
        get  
        {  
            return remoteLoader.FullName;  
        }  
    }  
}  
最后,修改我们WinForm上的Button Click事件处理过程,改为如下的形式:

private void button1_Click(object sender, EventArgs e)  

{  
    LocalLoader ll = new LocalLoader();  
    ll.LoadAssembly(@"C:\testlib.dll");  
    label1.Text = ll.FullName;  
    ll.Unload();  
}  
在完成上述的修改后,我们的程序也同样能够正确地显示assembly的FullName,而且,在显示完assembly信息后,程序会主动卸载新建的AppDomain,以防止testlib.dll的资源独占,影响其它程序的运行。

 

 

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

---------------------
作者:微wx笑
来源:CSDN
原文:https://blog.csdn.net/testcs_dn/article/details/8651402
版权声明:本文为博主原创文章,转载请附上博文链接!

转载于:https://www.cnblogs.com/ijunxiong/articles/11040234.html

你可能感兴趣的文章
Jenkins遇到问题一:jenkins配置权限不对导致无法登陆或者空白页面解决办法
查看>>
机器学习(十一)-------- 推荐系统(Recommender Systems)
查看>>
局部a链接样式
查看>>
Django-配置静态文件
查看>>
Spark内存管理详解
查看>>
插入排序
查看>>
问题:Linux 输入任何命令都显示 -bash: fork: Cannot allocate memory
查看>>
Aliyun cdn访问日志下载
查看>>
最新Dubbo-admin+Zookeeper搭建
查看>>
TFS支持移动设备,微软已经走出了第一步(手机上更新、查询工作项)
查看>>
oracle 超出表空间的空间限量解决方案
查看>>
C#中统计一个过程消耗的时间
查看>>
BZOJ 1083 [SCOI2005]繁忙的都市
查看>>
POJ 2965 The Pilots Brothers' refrigerator
查看>>
架构设计师能力模型
查看>>
给明年依然年轻的我们
查看>>
配置MOSS爬网时错误:访问被拒绝。请验证默认内容访问账户是否有权限
查看>>
JAVA基础之java体系结构
查看>>
Linux上的SQL Server的起步
查看>>
Linux下后台运行任务
查看>>