ASP.NET Core 2.0中Assembly.Load触发ReflectionTypeLoadException问题咨询
你遇到的这个问题其实很常见,核心原因是ASP.NET Core的程序集加载机制和Windows服务完全不同——Windows服务用的是传统的AppDomain加载模型,而ASP.NET Core默认使用AssemblyLoadContext来管理程序集加载,直接调用Assembly.Load经常会因为依赖项找不到或者加载上下文不匹配,导致在访问DefinedTypes时抛出异常(这个异常不是在Assembly.Load时触发,所以你的try-catch没抓到)。
下面给你几个针对性的解决方案,按优先级排序:
1. 改用从指定路径加载程序集(最可靠)
不要用Assembly.Load通过程序集名称加载,而是直接从应用的输出目录加载指定的DLL文件,这样能确保依赖项也能被正确解析。示例代码如下:
using System.Reflection; using System.Runtime.Loader; using System.IO; // 获取ASP.NET Core应用的根目录(bin目录) var basePath = AppContext.BaseDirectory; // 拼接DLL的完整路径 var dataDllPath = Path.Combine(basePath, "EnterpriseDirectory.Data.dll"); var businessDllPath = Path.Combine(basePath, "EnterpriseDirectory.Web.Business.dll"); // 使用AssemblyLoadContext加载程序集 var dataAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(dataDllPath); var businessAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(businessDllPath); // 注册程序集中的Autofac模块 builder.RegisterAssemblyModules(dataAssembly, businessAssembly);
这种方式能明确指定程序集的位置,避免加载上下文混乱导致的依赖问题。
2. 排查具体的依赖缺失问题
ReflectionTypeLoadException本质是程序集中的某些类型依赖的其他DLL找不到,但这个异常不会在Assembly.Load时抛出,只会在访问DefinedTypes(比如Autofac扫描模块时)才触发。你可以手动加一段代码来捕获具体的错误信息:
try { // 模拟Autofac访问DefinedTypes的操作 var types = dataAssembly.DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { foreach (var loaderException in ex.LoaderExceptions) { // 这里会输出具体的依赖缺失信息,比如"无法加载文件或程序集XXX" Console.WriteLine($"依赖加载失败: {loaderException.Message}"); } }
根据输出的信息,检查对应的DLL是否存在于ASP.NET Core的输出目录中。如果缺失,需要调整相关项目的“复制到输出目录”设置:
- 打开数据/业务DLL的项目属性
- 切换到“生成”选项卡
- 设置“复制到输出目录”为如果较新则复制或始终复制
3. 简化Autofac模块注册(前提是依赖完整)
如果你的数据和业务DLL已经被正确复制到ASP.NET Core的输出目录,也可以直接用程序集名称注册,不过要确保所有依赖项都存在:
builder.RegisterAssemblyModules( Assembly.Load("EnterpriseDirectory.Data"), Assembly.Load("EnterpriseDirectory.Web.Business") );
这种方式更简洁,但不如路径加载可靠,一旦依赖缺失还是会出现同样的问题。
4. 排查单文件发布模式(如果是发布后出现问题)
如果是发布为单文件应用(Single File),ASP.NET Core会把所有程序集打包到一个EXE中,此时直接加载外部DLL会有问题。你需要:
- 在发布设置中排除数据/业务DLL,不打包进单文件
- 确保这些DLL和EXE放在同一目录下
- 还是用路径加载的方式来加载程序集
总结一下,你之前的操作问题在于没有考虑到ASP.NET Core和Windows服务的程序集加载机制差异,直接沿用了Windows服务的加载方式,导致依赖解析失败。用路径加载+检查依赖缺失的方式,基本能解决这个问题。
内容的提问来源于stack exchange,提问作者Michal

