C#: Could not load file or assembly
Exception:
Could not load file or assembly 'DllFileName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5cadd04e079758c3' or one of its dependencies. The system cannot find the file specified.
最近在研究动态读取非当前EXE目录的DLL文件的方法。
Reflection, Activator.CreateInstance,或者AppDomain啥的。
当只读取单个Dll的时候没啥问题,但是当这个Dll以来和它同一个文件夹的dll时,就会报错。
搜了很久,终于搜到篇靠谱的文章。
http://theraneman.blogspot.com/2010/04/creating-instance-of-type-outside.html
文章是2010年的,10年过去了,呵呵。。。
大致解决方法代码如下,直接COPY过来留个念,慢慢啃。
1. 一般操作,会导致报错
Assembly assembly = Assembly.LoadFrom(C:\Sample\Sample.dll); Type appType = assembly.GetType(MyType); object objClassInstance = Activator.CreateInstance(appType);
2. 解决方案一
有点过的方案,哈哈,
使用这个方法,不能直接实例化你需要的函数,而必须实例化一个继承了MarshalByRefObject的函数,
入下面代码中的SampleProxy
Assembly assembly = Assembly.LoadFrom(@"C:\Sample\Sample.dll"); AppDomainSetup setup = new AppDomainSetup(); setup.ApplicationBase = @"C:\Sample\"; AppDomain appDomain = AppDomain.CreateDomain("AppHostDomain", null, setup); object obj = appDomain.CreateInstanceFromAndUnwrap(@"C:\Sample\Sample.dll", "SampleProxy");
3.解决方案二
被原作者成为冗余啰嗦的方案,不过在我看来挺好的。
该方案将循环递归加载所依赖的DLL
Assembly assembly = Assembly.LoadFrom(@"C:\Sample\Sample.dll");
AssemblyName[] arr = assembly.GetReferencedAssemblies(); LoadAssembly(arr); private void LoadAssembly(AssemblyName[] arr) { Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); List<string> names = new List<string>(); foreach (Assembly assem in loadedAssemblies) { names.Add(assem.FullName); } foreach (AssemblyName aname in arr) { if (!names.Contains(aname.FullName)) { try { Assembly loadedAssembly = Assembly.LoadFrom(@"C:\Sample\" + aname.Name + ".dll"); AssemblyName[] referencedAssemblies = loadedAssembly.GetReferencedAssemblies(); LoadAssembly(referencedAssemblies); } catch (Exception ex) { continue; } } } }
3. 解决方案三
定于当前AppDomain的一个事件,就是当需要哪个Assembly而又找不到时,就会触发。
Assembly assembly = Assembly.LoadFrom(@"C:\Sample\Sample.dll"); AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); object obj = Activator.CreateInstanceFrom(@"C:\Sample\Sample.dll", "MyType"); Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { string path = @"C:\Sample\Sample.dll"; string test = path.Substring(0,path.LastIndexOf(@"\")); string[] arr = args.Name.Split(','); string assemblyName = args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll"; string newPath = System.IO.Path.Combine(test, assemblyName); return Assembly.LoadFrom(newPath); }