.NET Core同路径加载程序集后类型不相等:是设计还是Bug?
问题分析:.NET Core 2.1.4中重复加载程序集导致类型不匹配
这其实是.NET Core 2.x版本里一个已知的设计行为,而非Bug,核心原因在于.NET Core和.NET Framework的程序集加载机制差异,尤其是程序集加载上下文(Assembly Load Context, ALC)的设计不同。
为什么.NET Framework不会出现这个问题?
在.NET Framework中,默认的程序集加载器会维护一个全局缓存,只要程序集的路径(或强名称)一致,重复加载时会直接返回已加载的程序集实例。因此,从同一个文件加载的程序集是同一个实例,对应的同名类型自然也相等。
.NET Core 2.1.4中为什么会出现类型不相等?
在早期的.NET Core(2.x系列)中,ALC的设计更偏向于隔离性,主要是为了更好地支持插件化、模块化场景:
- 当你通过
Type.Assembly.Location获取路径,再用Assembly.LoadFrom(path)这类方法加载时,CLR会创建一个新的独立ALC来加载该程序集,而不是复用原来的ALC。 - 在CLR的规则里,类型的唯一性由「程序集实例 + 类型全名」共同决定。不同ALC加载的程序集属于不同的实例,哪怕是同一个文件,对应的同名类型也会被视为完全不同的类型,自然会导致断言失败。
这是设计如此的原因
.NET Core引入ALC是为了解决.NET Framework中程序集加载冲突的问题(比如不同插件依赖同一程序集的不同版本)。早期版本的ALC设计优先保证隔离性,默认不会自动复用已加载的程序集实例,除非你显式指定共享上下文。
不过这个行为在后续的.NET Core 3.0+版本中做了优化,加载机制变得更智能,会尽量复用已加载的程序集,减少这类类型不匹配的问题。
解决办法(针对.NET Core 2.1)
- 最简单的方式:直接复用原类型所在的程序集实例,比如用
originalType.Assembly代替重新加载,这样类型肯定是同一个。 - 如果必须从路径加载,要确保使用同一个ALC:调用
AssemblyLoadContext.Default.LoadFromAssemblyPath(path),这样会使用默认上下文,和原程序集的上下文一致,加载后的类型就会和原类型相等。
内容的提问来源于stack exchange,提问作者Iravanchi
相关产品推荐
相关产品推荐

