C#.Net 如何动态加载与卸载程序集(.dll或者.exe)2----通过应用程序域AppDomain加载和卸载程序集之后,如何再返回原来的主程序域
实现目的:动态加载dll,执行完毕之后可以随时卸载掉,并可以替换这些dll,以在运行中更新dll中的类。
其实就是通过应用程序域AppDomain加载和卸载程序集。
在这方面微软有篇文章http://www.microsoft.com/china/msdn/archives/library/dncscol/html/csharp05162002.asp介绍的比较详细;Wayfarer's Prattle同志也有一篇http://www.cnblogs.com/wayfarer/archive/2004/09/29/47896.html文章。
具体实现起来倒也不难,我的问题是:可以加载了,可以卸载了,但是不同域的实例是通过代理来实现调用的(这是可以动态加载/卸载的基础),从主域调用子域中的没问题,反之如何让子域中的类来访问主域中的实例呢?
先说动态加载和卸载,前面两篇文章已经有很精彩的论述了,只说几个要点
1:主域中创建子域,加载的dll来自别的文件夹
AppDomain svcDomain = null;
try
{
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
setup.PrivateBinPath = setup.ApplicationBase;
setup.ApplicationName = asmName.FullName;
setup.ShadowCopyDirectories = setup.ApplicationBase+@"dlls"; //dll不是来自bin目录下(很奇怪,为什么有很多人认为dll必须就在bin目录下)
setup.ShadowCopyFiles = "true";
svcDomain = AppDomain.CreateDomain(asmName.FullName, null, setup);
}
catch (Exception ex)
{
Log.Write("test","can not CreateDomain")
return;
}
// Get remote service handler
ServiceProxy svc = null;
try
{ //关键点
svc = (ServiceProxy) svcDomain.CreateInstanceFromAndUnwrap(
svcDomain.BaseDirectory + "\\Services.dll", "MaServices.ServiceProxy");
}
catch (Exception ex)
{
AppDomain.Unload(svcDomain);
Log.Write("test", "can not create proxy")
return;
}
2:proxy的定义,一定要继承自MarshalByRefObject,传递的数据对象一定要可以序列化
public class ServiceProxy: MarshalByRefObject,IDisposable
3:proxy中加载dll
public bool LoadService(string assemblyName)
{
Assembly assembly = null;
try
{ assembly = Assembly.LoadFrom(assemblyName);
IService sev = (IService)assembly.CreateInstance(typename, true);
this.services[assemblyName]=sev ;
}
4:proxy中调用具体的类:注意,具体调用一定不能再主域中
public IContext RunService(string serviceName,IContext ctx)
{
object o = this.service[serviceName];
((IService)o).RunService(ctx);
return ctx;
}
最后,主域中直接调用既可
proxy.RunService(xx,xx)
就这些。这样程序就可以随时加载一个dll(位置任意),反射得到类,运行,这个dll随时可以被替换
几个关键点:
代理不要返回被反射的实例,传递的数据要可以序列化,注意设置ShadowCopyDirectories。
现在言归正传,说说问题
假设主域M,子域C1,C2。通过代理之后,M可以调用C1和C2中的实例,反过来,如何让C1调用M中的实例呢?或者C1调用C2中的实例?
tcp通讯是一种方法,但是系统消耗太大,频繁使用那就糟透了。
谁有高招?
还有一个问题:看上述文章时发现,他们的prxoy在返回时都是返回的要代理的类的实例,对于这一点我比较怀疑。如果dll不在一个目录下,那么本地将无法接受这个实例。所以要求本地必须有这么一个dll存在,才能接受这个返回结果,然后根据本地的dll中定义的类的结构来反序列化。这样一来,不论如何使用proxy,其实在DefaultAppDomain里面都引用了具体的类和dll,所以导致dll是被当前程序占用的,无论如何都不能被替换。
相关文章
- C#.Net 如何动态加载与卸载程序集(.dll或者.exe)5-----Assembly.Unload
- C#.Net 如何动态加载与卸载程序集(.dll或者.exe)4-----Net下的AppDomain编程 [摘录]
- C# 框架是什么?MVC是什么 ?工厂模式是什么?设计模式是什么?三层架构是什
- C# Eval在aspx页面中的用法及作用
- C#Redis集合set
- A2D JS框架 - DES加密解密 与 Cookie的封装(C#与js互相加密解密)
- C#.NET常见问题(FAQ)-如何生成release版本的程序,生成debug版本的程序
- .NET(C#) Internals: as a developer, .net framework in my eyes
- Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化
- asp.net中C#中计算时间差代码
- asp.net C#检查URL是否有效
- ASP.NET 运行状况监视的日志记录错误详细信息 (C#)
- .NET/C#中对自定义对象集合进行自定义排序的方法
- c# 线程的优先级
- C#.NET万能数据库访问封装类(ACCESS、SQLServer、Oracle)
- C# DataTable 用法小结
- Atitit,通过pid获取进程文件路径 java php c#.net版本大总结
- Atitit.得到网络邻居列表java php c#.net python
- paip.java c# .net php python调用c++ c dll so windows api 总结
- 你的NET程序需要保护吗?Agile.net 6.6.X 注入式Crack
- c#QQ连连看辅助
- C# datagridview CheckBox勾选问题
- 【设计模式】状态模式(C#)
- C#实现单例模式和实现思路