实现目的:动态加载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)2----通过应用程序域AppDomain加载和卸载程序集之后,如何再返回原来的主程序域的更多相关文章

  1. 通过应用程序域AppDomain加载和卸载程序集

    微软装配车的大门似乎只为货物装载敞开大门,却将卸载工人拒之门外.车门的钥匙只有一把,若要获得还需要你费一些心思.我在学习Remoting的时候,就遇到一个扰人的问题,就是Remoting为远程对象仅提 ...

  2. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)0-------通过应用程序域AppDomain加载和卸载程序集

    本博客中以“C#.Net 如何动态加载与卸载程序集(.dll或者.exe)”开头的都是引用莫问奴归处 微软装配车的大门似乎只为货物装载敞开大门,却将卸载工人拒之门外.车门的钥匙只有一把,若要获得还需要 ...

  3. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)6-----在不卸载程序域的前提下替换程序集文件。

    当某个程序集文件被载入AppDomain,该文件在AppDomain.Unload之前是不能被替换和删除的.使用AppDomainSetup的影像复制功能可以实现在不卸载程序的情况下替换或者删除程序集 ...

  4. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)4-----Net下的AppDomain编程 [摘录]

    最近在对AppDomain编程时遇到了一个问题,卸载AppDomain后,在内存中还保留它加载的DLL的数据,所以即使卸载掉AppDomain,还是无法更新它加载的DLL.看来只有关闭整个进程来更新D ...

  5. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)3---- 动态加载Assembly应用程序

    下载 supergraphfiles.exe 示例文件. 应用程序体系结构 在我专攻代码之前,我想谈谈我尝试做的事.您可能记得,SuperGraph 让您从函数列表中进行选择.我希望能够在具体的目录中 ...

  6. [UE4]C++实现动态加载的问题:LoadClass<T>()和LoadObject<T>() 及 静态加载问题:ConstructorHelpers::FClassFinder()和FObjectFinder()

    转自:http://aigo.iteye.com/blog/2281558 动态加载UObject和动态加载UClass分别用LoadObject<T>(),和LoadClass<T ...

  7. [ActionScript 3.0] AS3.0 Loader加载子swf时是否需要指定新的应用程序域ApplicationDomain

    实际应用中, Loader加载子swf时是否需要指定新的应用程序域ApplicationDomain,需要择情况而定. 1.如果在本地将项目位置添加到flashplayer受信任位置(上一篇文章所述) ...

  8. AppDomain加载与释放dll

    AppDomain加载与释放dll 几年前写过同名随笔,但今天应不大适用了.但还有几个朋友留言关注,我重新发布相关代码. 首先我们的目的就是运行期间更新dll,并应用dll.这个过程需要应用 AppD ...

  9. Windows2003系统问题:“无法加载安装程序库wbemupgd.dll,或是找不到函数OcEntry.

    “无法加载安装程序库wbemupgd.dll,或是找不到函数OcEntry.请与您的系统管理员联系.特定错误码是 0x7e;" 然后是警告框: " 无法初始化应用程序." ...

随机推荐

  1. DTCMS更改图片相册上传图片类型,手机上传图片相册

    /admin/js/uploader.js 中 filetypes: "jpg,jpge,png,gif", //文件类型 改为 filetypes: "jpg,jpeg ...

  2. 【转】SQL 2008 Insert返回自动编号id三种方法比较

    SQL Server 2008中,insert数据的时候返回自动编号的id,有三种方法实现SCOPE_IDENTITY.IDENT_CURRENT 和 @@IDENTITY, 它们都返回插入到 IDE ...

  3. webpack减少打包后文件体积的几种方法

    webpack 把我们所有的文件都打包成一个 JS 文件,这样即使你是小项目,打包后的文件也会非常大.下面就来讲下如何从多个方面进行优化. 去除不必要的插件 刚开始用 webpack 的时候,开发环境 ...

  4. ZENCART 打开/关闭日志文件

    优秀的php开源程序很多都只带生成日志文件的功能,这类功能的开发可以帮助到站长在调试网站的时候及时的改正网站存在的错误,但是这类错误日志由来并非网站出现什么严重不可挽救的错误,大部分是一些未定义变量这 ...

  5. Android:使用命令行工具adb、mksdcard等

    有一些Android的工具需要在命令行的环境中运行,只是可以选择Windows的开始->运行,键入cmd并确定,进入命令行的界面中运行.主要的命令行工具包括adb和mksdcard等.命令行的工 ...

  6. fedora 解决yumBackend.py进程CPU占用过高

    fedora启动时电脑风扇噪声巨响,检查进行发现是yumBackend.py进行占用CPU过高. yumBackend.py进行是后台检查更新,如果觉得没用可以使用工具关闭检查更新,或者修改检查周期. ...

  7. JavaScript技巧45招

    原文:45 Useful JavaScript Tips, Tricks and Best Practices作者:Saad Mousliki 在这篇文章里,我将分享一些JavaScript的技巧.秘 ...

  8. 外部表查询时出现ORA-29913和ORA-29400错误

    create table t_ext_tab(id char(1),name char(6)) organization external( type oracle_loader default di ...

  9. 【android-cocos2d-X2.2 环境配置】在Mac下搭建Cocos2d-X-android开发环境!

    仅用于cocos2d-X2.2--cocos2d-X3.4 原文地址:http://blog.csdn.net/dingkun520wy/article/details/17097593 (1)下载 ...

  10. Code for the Homework1 改进

    #include <iostream> #include <vector> #include "shape.h" //using namespace std ...