zoukankan      html  css  js  c++  java
  • winform下的dll加载与卸载 插件式应用

           最近在更改一个项目的,开会研究之后希望可以做成插件的方式来实现。项目本身程序是基于2.0开发的。自己做了一个打包工具,具体实现用另外一个文章来描述吧。
           根据网上搜的资料http://www.cnblogs.com/chinhr/archive/2007/09/01/878242.html 发现加载还是个很容易的事情,麻烦的是在卸载这一环节。
     
    一:通过Assembly加载
          ①加载:通过Assembly加载可以直接加载,和先加载到内存中,在通过内存读取dll,我使用的是后者(因为直接加载会出现一系列问题),我使用的是Form窗体;
         
     FileStream fs = new FileStream(loadPath, FileMode.Open, FileAccess.Read);
                    BinaryReader br = new BinaryReader(fs);
                    byte[] bFile = br.ReadBytes((int)fs.Length);
                    br.Close();
                    fs.Close();
                    Assembly dll = Assembly.Load(bFile);
                    Type type = dll.GetType("PluginDemo.PluginDemo");
                    Form form = (Form)Activator.CreateInstance(type);
                    form.ShowDialog();
    
         loadPath为dll路径,dll.GetType("类库.文件名")。这样的效果就是,通过加载dll,反射来打开我的插件窗体
          ②卸载
             此方法你是通过将dll转成字节,放到内存中,再去内存中读取要反射dll,所以在你删除的时候可以直接删除。但是此方法有一个缺点,就是你只可以删除放到内存中读取的dll,但是这个dll引用的其他dll,你删除的时候会提示无法删除
    二:通过AppDomain(程序域 )加载(借鉴http://www.cnblogs.com/chinhr/archive/2007/09/01/878242.html 这篇文章)
             因为Assembly并没直接提供unload方法,只提供了各种load方法,所用通过Assembly无法实现dll的卸载。然后由于插件的热插拔效果,所以我们必须想办法通过其他途径达到卸载的目的。
             这时候我们想通过在主程序域中创建子程序域,然后对子程序域提供创建和删除。创建和删除子程序域并不困难,AppDomain已经提供了相应的方法,难点是在两个程序域之间的通信。而在这里我们使用代理来达到这一个需求。通过子程序域来实现的类和窗体,一定要继承MarshalByRefObject,否则会提示当前类(窗体未序列化)
              加载代码:
                   主窗体加载代码:
                        
    PermissionSet perSet = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.Unrestricted);
                    AppDomainSetup objSetup = new AppDomainSetup();
                    objSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
                    _objAppDomain = AppDomain.CreateDomain("MyAppDomain", null, objSetup, perSet, null);
                    RemoteLoaderFactory factory = (RemoteLoaderFactory)_objAppDomain.CreateInstance("DemoForm", "DemoForm.RemoteLoaderFactory").Unwrap();
                    IRemoteInterface _object = factory.Create("PluginDemo.dll", "PluginDemo.MyRemoteInterface", null);
                    if (_object == null)
                    {
                        string strErrorMsg = "Error: " + "Couldn't load class.";
                        MessageBox.Show(strErrorMsg);
                    }
                    else
                    {
                        _object.Run();
                    }

         代理方法:

         

       public class RemoteLoaderFactory : MarshalByRefObject
        {
            private const BindingFlags bfi = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;
    
            public RemoteLoaderFactory() { }
    
            public IRemoteInterface Create(string assemblyFile, string typeName, object[] constructArgs)
            {
                return (IRemoteInterface)Activator.CreateInstanceFrom(
                         assemblyFile, typeName, false, bfi, null, constructArgs,
                         null, null, null).Unwrap();
            }
        }
    
     
                 
    反射的插件代码:
      
        public class MyRemoteInterface : MarshalByRefObject,IRemoteInterface
        {
            #region IRemoteInterface 成员
            public void Run()
            {
                PluginDemo pluginDemo = new PluginDemo();
                pluginDemo.ShowDialog();
            }
            #endregion
        }
    
    卸载:
      卸载代码:   
        AppDomain .Unload(_objAppDomain);
    相对于直接加载到内容,使用程序域来实现加载卸载的时候,可以直接删除任何它关联的dll.
     
    下面是我自己做的一个demo,附上链接提供下载:AppDomainDemo
    界面仿照上面的博客来的:添加程序集的时候,需要添加AppDomainDemo\PluginDemo\bin\Debug下的PluginDemo.dll,才可以,因为测试程序中写死了。
    测试反射类库引用Test类库的信息的时候,记得将Test.dll放到主程序目录下,否侧会找不到的。
    以上是自己查找资料总结的,所过哪里有错误,还望指正^_^,下一篇把自己做的工具上传上来
     
     
  • 相关阅读:
    Qt程序使用Win32 API发送ZPL指令与斑马打印机通信
    Eclipse构建Maven项目
    编码风格 缩进和空白
    Linux下Tomcat重新启动
    linux下tomcat服务的相关命令
    第一天
    Day1NLP_机器翻译
    Day4_attention is all you need 论文阅读下篇
    Day_7tensorflow 实战
    Day5_python学习
  • 原文地址:https://www.cnblogs.com/hualuohuakaihuamanyuan/p/5050573.html
Copyright © 2011-2022 走看看