c#动态加载卸载DLL

时间:2022-01-12 14:45:49

  前段时间工作的时候遇到一个问题。就是需要每次启动程序的时候动态替换掉某个dll,所以就百度了这方面的资料。这次记录下来让自己以后可以看。

  根据自己的理解,动态卸载dll需要有以下条件:

    1:dll在加载在Appdomin(应用程序域)中,从而通过卸载Appdomin来动态卸载dll。

  

  以下代码从网上抄过来的,加上了一些注释。

--------------------------------------------------------------------------------------------------------主程序代码-------------------------------------------------------------------------------------------------------

namespace UnloadDllDemo
{
  class Program
  {
    static void Main(string[] args)
    {
    string callingDomainName = AppDomain.CurrentDomain.FriendlyName;//Thread.GetDomain().FriendlyName;
    Console.WriteLine(callingDomainName);
    AppDomain ad = AppDomain.CreateDomain("DLL Unload test");   //创建应用程序域

      //创建应用程序域的代理实例,其中代码必须继承 MarshalByRefObject,两个参数分别为代理类所在的程序集名称和完整类名
    ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap("UnloadDllDemo.exe", "UnloadDllDemo.ProxyObject"); 

    //动态加载dll
    obj.LoadAssembly();

    //调用代理类中的方法,三个参数分别为加载的dll中的完整类名,方法名,方法参数。
    obj.Invoke("MyDll.Class1", "Test", "It's a test");

    //卸载应用程序域实现dll的动态卸载
    AppDomain.Unload(ad);
    obj = null;
    Console.ReadLine();
    }
  }
  public class ProxyObject : MarshalByRefObject
  {
    Assembly assembly = null;
    public void LoadAssembly()
    {

      //动态加载dll
      assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory+@"MyDll.dll");
    }
    public bool Invoke(string fullClassName, string methodName, params Object[] args)
    {
      if (assembly == null)
      return false;
      Type tp = assembly.GetType(fullClassName);
      if (tp == null)
      return false;
      MethodInfo method = tp.GetMethod(methodName);
      if (method == null)
      return false;
      Object obj = Activator.CreateInstance(tp);
      method.Invoke(obj, args);
      return true;
    }
  }

} 

--------------------------------------------------------------------------------------------------------MyDll.dll代码------------------------------------------------------------------------------------------------------

namespace MyDll
{
  public class Class1
  {
    public Class1()
    { }

    public void Test(string Str)
    {
      Console.WriteLine(Str);
    }
  }
}

注意:

1. 要想让一个对象能够穿过AppDomain边界,必须要继承MarshalByRefObject类,否则无法被其他AppDomain使用。(我的理解是必须让代理类继承MarshalByRefObject才能让dll在AppDomain加载,否则dll只能在主程序中加载)。

2. 每个线程都有一个默认的AppDomain,可以通过Thread.GetDomain()来得到