.NET 4.0中Assembly.GetTypes()抛出ReflectionTypeLoadException如何解决?
解决方案:插件依赖加载失败导致ReflectionTypeLoadException
问题根源
.NET 4.0的程序集探测规则是:CLR优先从宿主应用的基目录查找依赖程序集,不会自动扫描插件所在的子目录。你的StevesStuff.CommonBridges.dll虽然和主插件同目录,但CLR加载主插件时,会去宿主应用目录找这个依赖,找不到就抛出加载异常,而宿主的扫描逻辑用空catch吞了这个异常,导致你的插件被忽略。
可行解决方法
1. 合并依赖到主插件DLL(最直接)
用ILMerge工具(兼容.NET 4.0版本)把依赖程序集合并到你的主插件中,让CLR加载主插件时直接获取到依赖类型:
- 下载适配.NET 4.0的ILMerge版本
- 执行命令行:
ilmerge /target:library /out:MergedPlugin.dll YourMainPlugin.dll StevesStuff.CommonBridges.dll - 将合并后的
MergedPlugin.dll替换原主插件文件即可。
2. 在插件静态构造函数中手动解析依赖
利用CLR加载程序集时会先执行静态构造函数的特性,在主插件的核心类中添加程序集解析逻辑,当CLR找不到依赖时,从插件目录手动加载:
using System; using System.IO; using System.Reflection; public class YourPluginMainClass : IThirdPartyPluginInterface { // 静态构造函数,在CLR加载程序集时自动执行 static YourPluginMainClass() { AppDomain.CurrentDomain.AssemblyResolve += (sender, resolveArgs) => { var assemblyName = new AssemblyName(resolveArgs.Name); // 获取当前插件所在目录 string pluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string assemblyPath = Path.Combine(pluginDirectory, $"{assemblyName.Name}.dll"); if (File.Exists(assemblyPath)) { return Assembly.LoadFrom(assemblyPath); } return null; // 找不到则返回null,让CLR继续默认逻辑 }; } // 插件接口实现代码... }
3. 修改宿主程序的探测路径(若有权限)
如果你能修改宿主应用的app.config,可以添加<probing>元素,把插件所在目录加入CLR的程序集探测路径:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <!-- 替换为你的插件实际目录,多个目录用分号分隔 --> <probing privatePath="Plugins;YourSpecificPluginFolder"/> </assemblyBinding> </runtime> </configuration>
这个方法不需要修改插件代码,但前提是你有权限修改宿主的配置文件。
内容的提问来源于stack exchange,提问作者SteveDonie
相关产品推荐
相关产品推荐

