zoukankan      html  css  js  c++  java
  • .net 动态加载Dll

    在程序正在使用的过程中,常常需要升级DLL。这时,如果dll已经被主程序引用,则无法修改,这样的需求应该很常见。换个角度,可以理解成程序的升级或者修改Bug的功能。

    以下通过动态的加载Dll来解决这个问题。

    整个思路的前提是,动态调用的东西和前台需要的功能通过代理IBaseInterface连接起来,也就是说动态dll里面的类和Proxy都需要实现这个接口。

    namespace BaseInterface
    {
        public interface IBaseInterface
        {
            string GetString();
        }
    }

    核心代码:Proxy.dll

    namespace Proxy
    {
        internal class AppDomainCore
        {
            public AppDomain DefaultAppDomain { get; private set; }
            public string DefaultAppDomainName { get; private set; }
    
            public AppDomainCore(string appDomainName)
            {
                DefaultAppDomainName = appDomainName;
                AppDomainSetup setup = new AppDomainSetup();
                setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
                setup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
    
                Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
                DefaultAppDomain = AppDomain.CreateDomain(appDomainName, evidence, setup);
            }
    
            public bool ClearAppDomain()
            {
                try
                {
                    AppDomain.Unload(DefaultAppDomain);
                    DefaultAppDomain = null;
                    return true;
                }
                catch { return false; }
            }
    
            ~AppDomainCore()
            {
                ClearAppDomain();
            }
        }
    }
    namespace Proxy
    {
        internal class AssemblyCore
        {
            public string ActivedAssemblyName { get; private set; }
            public string CurrentType { get; private set; }
            public FileInfo DefaultAssemblyFile { get; private set; }
    
            public AssemblyCore(string assemblyName, string type)
            {
                ActivedAssemblyName = assemblyName;
                CurrentType = type;
    
                try
                {
                    DefaultAssemblyFile = new FileInfo(assemblyName);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
    }
    namespace Proxy
    {
        public class Proxy : BaseInterface.IBaseInterface
        {
            AssemblyCore _assemblyCore;
            AppDomainCore _appDomainCore;
    
            public string DefaultAssemblyName { get { return _assemblyCore.ActivedAssemblyName; } }
            public string DefaultAppDomainName { get { return _appDomainCore.DefaultAppDomainName; } }
    
            public Proxy(string assemblyName, string typeName, string appDomainName)
            {
                _assemblyCore = new AssemblyCore(assemblyName, typeName);
                _appDomainCore = new AppDomainCore(appDomainName);
            }
    
            public void UnLoad()
            {
                _appDomainCore.ClearAppDomain();
            }
    
            BaseInterface.IBaseInterface _proxy;
            public string GetString()
            {
                if (_proxy == null)
                    _proxy = _appDomainCore.DefaultAppDomain.CreateInstanceFromAndUnwrap(
                        _assemblyCore.ActivedAssemblyName, _assemblyCore.CurrentType) 
                        as BaseInterface.IBaseInterface;
                return _proxy.GetString();
            }
        }
    }

    以上代码在项目Proxy里面写入,是动态加载Dll的核心代码。

    在Proxy里面,其中AppDomainCore根据传递的参数生成新的AppDomain, AssemblyCore则根据传递的参数生成新的FileInfo. 在Proxy类里面,同时定义一个AssemblyCore和AppDomainCore,根据方法:_appDomainCore.DefaultAppDomain.CreateInstanceFromAndUnwrap(_assemblyCore.ActivedAssemblyName, _assemblyCore.CurrentType), 动态的生成实例,最后用as 转换成接口IBaseInterface,通过调用接口的GetString方法来调用dll里面的方法。

    一下为模拟的两个Dll类,

    namespace Assembly1
    {
        [Serializable]
        public class ClassLibrary : MarshalByRefObject, BaseInterface.IBaseInterface
        {
            public string GetString()
            {
                return "Assembly1.ClassLibrary";
            }
        }
    }
    namespace Assembly2
    {
        [Serializable]
        public class ClassLibrary : MarshalByRefObject, BaseInterface.IBaseInterface
        {
            public string GetString()
            {
                return "Assembly2.ClassLibrary";
            }
        }
    }

    分别生成到Assembly v1.0.dll和Assembly v2.0.dll中。

    最终的界面代码:

    namespace DynamicDll
    {
        public partial class Form1 : Form
        {
            Proxy.Proxy _proxy;
            public Form1()
            {
                InitializeComponent();
                LoadDll("Assembly v1.0.dll", "Assembly1.ClassLibrary", "Domain1");
                radV1.Click += (a, b) => LoadDll("Assembly v1.0.dll", "Assembly1.ClassLibrary", "Domain1");
                radV2.Click += (a, b) => LoadDll("Assembly v2.0.dll", "Assembly2.ClassLibrary", "Domain2");
            }
    
            void LoadDll(string assName, string type, string appName)
            {
                if (_proxy != null) _proxy.UnLoad();
                _proxy = new Proxy.Proxy(assName, type, appName);
                lblCurrentAppDomain.Text = _proxy.DefaultAppDomainName;
                lblCurrentAssembly.Text = _proxy.DefaultAssemblyName;
                lblMainAppDomain.Text = AppDomain.CurrentDomain.FriendlyName;
            }
    
            private void btnRes_Click(object sender, EventArgs e)
            {
                txtRes.Text = _proxy.GetString();
            }
        }
    }

     

    查看项目Dynamic的依赖项,可以很清楚的看到:它只依赖BaseInterface和Proxy两个项目,与Assembly v1.0和v2.0都无关。

    也就是说,程序运行的时候,可以修改Assembly v1.0和v2.0里面的代码,重新生成,同时替换运行目录下的dll。

  • 相关阅读:
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    SVN分支
    SVN分支
    SVN 版本回退
    SVN 版本回退
    如何在excel中取消合并单元格后内容自动填充?
    如何在excel中取消合并单元格后内容自动填充?
    如何让自己像打王者荣耀一样发了疯、拼了命的学习?
  • 原文地址:https://www.cnblogs.com/icyJ/p/dynamic_Dll.html
Copyright © 2011-2022 走看看