.net C#加载程序集外dll文件方法

Posted xuanyuanhw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.net C#加载程序集外dll文件方法相关的知识,希望对你有一定的参考价值。

参考帖子:(20条消息) C#如何加载程序运行目录外的程序集_c# probing privatepath_Jlins的博客-CSDN博客

(20条消息) Assembly resolve(自定义加载指定目录的程序集)_assemblyresolve_Mr蹇的博客-CSDN博客

这里感谢作者提供的信息!

我们在做程序开发时,总会引用各种各样的dll,有时候不想把dll文件放到主程序同一目录下,而是放到指定目录多个程序共享它,这时候需要借助AppDomain.CurrentDomain.AssemblyResolve事件。

  1. Visual Studio中添加dll文件的引用,复制本地改为False。
  2. 在程序初始化时添加监视事件 AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 
  3. 在监听事件中处理自己指定目录的dll,这里我把多个dll处理写在一个方法中了,按主程序使用dll的顺序依次加载
            static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
            
                Dictionary<string, string> dicDll = new Dictionary<string, string>();
                dicDll.Add("LinqToExcel.dll", @"C:\\Users\\Public\\Documents\\Alpha_Resources\\LinqToExcel.dll");
                dicDll.Add("MiniExcel.dll", @"C:\\Users\\Public\\Documents\\Alpha_Resources\\MiniExcel.dll");
    
                if (string.IsNullOrWhiteSpace(args.Name))
                
                    return null;
                
    
                string dllName = args.Name.Split(\',\')[0] + ".dll";
    
                //判断是否已经加载过
                foreach (var itemAssm in AppDomain.CurrentDomain.GetAssemblies())
                
                    if (dicDll.Keys.Contains(itemAssm.ManifestModule.Name))
                    
                        return itemAssm;
                    
                
    
                //将文件以二进制方式读取到内存,此方法可解决文件被占用的问题
                byte[] buffer = System.IO.File.ReadAllBytes(dicDll[dllName]);
                //加载内存中的文件
                return Assembly.Load(buffer);
    
            

     

 

C#中如何动态加载和卸载DLL

在C#中我们也能使用Assembly.LoadFile实现动态加载DLL,但是当你试图卸载时,你会很惊讶的发现Assembly没有提供任何卸载的方法。这是由于托管代码的自动垃圾回收机制会做这件事情,所以C#不提供释放资源的函数,一切由垃圾回收来做。powered by 25175.net这引发了一个问题,用Assembly加载的DLL可能只在程序结束的时候才会被释放,这也意味着在程序运行期间无法更新被加载的DLL。而这个功能在某些程序设计时是非常必要的,考虑你正在用反射机制写一个查看DLL中所有函数详细信息的程序,程序提供一个菜单让用户可以选择DLL文件,这时就需要让程序能够卸载DLL,否则一旦用户重新得到新版本DLL时,必须要重新启动程序,重新选择加载DLL文件,这样的设计是用户无法忍受的。C#也提供了实现动态卸载DLL的方法,通过AppDomain来实现。AppDomain是一个独立执行应用程序的环境,当AppDomain被卸载的时候,在该环境中的所有资源也将被回收。关于AppDomain的详细资料参考MSDN。下面是使用AppDomain实现动态卸载DLL的代码,usingSystem;usingSystem.Collections.Generic;usingSystem.Text;usingSystem.Threading;usingSystem.Reflection;namespaceUnloadDllclassProgramstaticvoidMain(string[] args)stringcallingDomainName = AppDomain.CurrentDomain.FriendlyName;//Thread.GetDomain().FriendlyName;Console.WriteLine(callingDomainName);AppDomain ad = AppDomain.CreateDomain("DLL Unload test");ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap(@"UnloadDll.exe","UnloadDll.ProxyObject");obj.LoadAssembly();obj.Invoke("TestDll.Class1","Test","It's a test");AppDomain.Unload(ad);obj =null;Console.ReadLine();classProxyObject : MarshalByRefObjectAssembly assembly =null;publicvoidLoadAssembly()assembly = Assembly.LoadFile(@"TestDLL.dll");publicboolInvoke(stringfullClassName,stringmethodName,paramsObject[] args)if(assembly ==null)returnfalse;Type tp = assembly.GetType(fullClassName);if(tp ==null)returnfalse;MethodInfo method = tp.GetMethod(methodName);if(method ==null)returnfalse;Object obj = Activator.CreateInstance(tp);method.Invoke(obj, args);returntrue;注意:1. 要想让一个对象能够穿过AppDomain边界,必须要继承MarshalByRefObject类,否则无法被其他AppDomain使用。 参考技术A 1、利用反射进行动态加载和调用.
Assembly assembly=Assembly.LoadFrom(DllPath); //利用dll的路径加载,同时将此程序集所依赖的程序集加载进来,需后辍名.dll
Assembly.LoadFile 只加载指定文件,并不会自动加载依赖程序集.Assmbly.Load无需后辍名
2、加载dll后,需要使用dll中某类.
Type type=ass.GetType(“TypeName”);//用类型的命名空间和名称获得类型
3、需要实例化类型,才可以使用,参数可以人为的指定,也可以无参数,静态实例可以省略
Object obj = Activator.CreateInstance(type,params[]);//利用指定的参数实例话类型
4、调用类型中的某个方法:
需要首先得到此方法
MethodInfo mi=type.GetMethod(“MehtodName”);//通过方法名称获得方法
5、然后对方法进行调用,多态性利用参数进行控制
mi.Invoke(obj,params[]);//根据参数直线方法,返回值就是原方法的返回值
参考技术B 难道不是自动的吗?

以上是关于.net C#加载程序集外dll文件方法的主要内容,如果未能解决你的问题,请参考以下文章

C#动态加载dll 时程序集的卸载问题

C#中如何动态加载和卸载DLL

c# .NET 加载/卸载程序集,同时保持相同的会话

C# Assembly.Load() 方法加载了错误的 dll?

C# 将HTML转为XML

加载本机 dll 时抛出 ExecutionEngineException