为何Assembly.LoadFrom加载GAC旧版本强命名程序集而非指定路径?
问题原因分析
你遇到的情况大概率是绑定重定向在起作用:虽然你指定了要加载4.0.3.0版本的System.ValueTuple,但项目的配置文件(app.config/web.config)里可能存在自动生成或手动添加的绑定重定向规则,把4.0.3.0的请求强制重定向到了GAC中的4.0.0.0版本。另外,部分.NET Framework版本会默认启用自动绑定重定向,自动将高版本请求映射到已安装的低兼容版本,这就导致CLR跳过了指定路径的加载,直接从GAC取了重定向后的版本。
解决办法
以下几种方式可以强制CLR从指定路径加载目标版本:
修正绑定重定向规则
打开项目的配置文件,找到<runtime>节点下的<assemblyBinding>,添加或修改System.ValueTuple的绑定规则,确保指向你需要的4.0.3.0版本:<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" /> </dependentAssembly> </assemblyBinding> </runtime>如果之前有指向4.0.0.0的重定向规则,直接替换即可。
使用
Assembly.LoadFile替代LoadFromLoadFile方法会完全绕过CLR的程序集探测逻辑(包括GAC和绑定策略),直接从指定路径加载程序集。但要注意:该方法会加载同一程序集的多个副本(若路径不同),可能导致类型兼容性问题(同一类型在不同副本中会被视为不同的Type对象)。示例代码:Assembly assembly = Assembly.LoadFile(@"你的程序集完整路径");订阅
AppDomain.AssemblyResolve事件
在应用程序启动时注册该事件,拦截CLR的程序集加载请求,当检测到是System.ValueTuple 4.0.3.0的请求时,手动从指定路径加载:AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { var targetAssembly = new AssemblyName(args.Name); if (targetAssembly.Name.Equals("System.ValueTuple", StringComparison.Ordinal) && targetAssembly.Version == new Version("4.0.3.0")) { string targetPath = @"你的程序集完整路径"; return Assembly.LoadFrom(targetPath); } return null; };这个方法能精准控制特定程序集的加载来源,且不会影响其他程序集的正常探测逻辑。
禁用自动绑定重定向
如果是.NET Framework项目,可以在项目文件(.csproj)中添加以下配置,关闭自动生成绑定重定向的功能,避免系统自动覆盖你的版本需求:<PropertyGroup> <AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects> </PropertyGroup>
内容的提问来源于stack exchange,提问作者Very Professional Username

