使用反射调用依赖第三方DLL的方法时遇加载失败问题求助
问题场景
DemoImport.dll定义(依赖RestSharp NuGet包)
using RestSharp; namespace DemoImport; public class ImportClass { public void JustAMethod() { Console.WriteLine("Hello"); var client = new RestClient(); } }
反射调用的DemoClient代码
using System.Reflection; Assembly assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + "\\Demo.dll"); Type? type = assembly.GetType("DemoImport.ImportClass"); object instance = Activator.CreateInstance(type)!; type.GetMethod("JustAMethod").Invoke(instance, Array.Empty<object>());
执行时错误
Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.IO.FileNotFoundException: Could not load file or assembly 'RestSharp, Version=109.0.1.0, Culture=neutral, PublicKeyToken=598062e77f915f75'. 系统找不到指定的文件。
File name: 'RestSharp, Version=109.0.1.0, Culture=neutral, PublicKeyToken=598062e77f915f75'
at DemoImport.ImportClass.JustAMethod()
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at Program.<Main>$(String[] args) in F:\Program.cs:line 6
解决方案
1. 复制第三方依赖DLL到执行目录
CLR加载程序集时,会优先在当前执行目录、系统目录等默认路径查找依赖项。只需将对应版本的RestSharp.dll复制到DemoClient的执行目录(与Demo.dll同目录即可)。
- 若DemoImport项目使用NuGet管理RestSharp,可在项目中设置RestSharp的
复制本地属性为True,编译后RestSharp.dll会输出到DemoImport的bin目录,直接复制该DLL到DemoClient运行目录即可。
2. 注册程序集解析事件
通过AppDomain.CurrentDomain.AssemblyResolve事件,在CLR找不到依赖程序集时手动指定路径加载。修改DemoClient代码如下:
using System.Reflection; using System.IO; // 注册程序集解析事件 AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { var assemblyName = new AssemblyName(args.Name); // 指定RestSharp.dll的路径,这里假设和Demo.dll同目录 var dllPath = Path.Combine(Directory.GetCurrentDirectory(), $"{assemblyName.Name}.dll"); if (File.Exists(dllPath)) { return Assembly.LoadFrom(dllPath); } return null; }; // 原反射调用代码 Assembly assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + "\\Demo.dll"); Type? type = assembly.GetType("DemoImport.ImportClass"); object instance = Activator.CreateInstance(type)!; type.GetMethod("JustAMethod")?.Invoke(instance, Array.Empty<object>());
3. 使用Assembly.LoadFrom替代Assembly.LoadFile
Assembly.LoadFile仅加载指定的DLL,不会自动解析其依赖;而Assembly.LoadFrom会加载指定DLL,并尝试从该DLL所在目录自动查找依赖项。修改反射加载代码:
Assembly assembly = Assembly.LoadFrom(Path.Combine(Directory.GetCurrentDirectory(), "Demo.dll"));
只要RestSharp.dll和Demo.dll处于同一目录,CLR会自动加载该依赖。
4. 确保DemoImport项目发布时包含所有依赖
若使用.NET Core/.NET 5+,在DemoImport项目的.csproj文件中添加以下配置,编译或发布时会自动复制所有NuGet依赖DLL到输出目录:
<PropertyGroup> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> </PropertyGroup>
之后将Demo.dll及输出目录下的所有依赖DLL一起复制到DemoClient的运行目录即可。
内容的提问来源于stack exchange,提问作者DamXosp4j

