.NET Framework 4.8类库为何寻找Microsoft.Bcl.AsyncInterfaces 6.0.0?
我有一个基于.NET Framework 4.8的Redis类库,引用了NuGet包StackExchange.Redis 2.1.58(该包依赖Microsoft.Bcl.AsyncInterfaces 1.1.1或更高版本)。当前使用的ASP.NET Web API未安装Microsoft.Bcl.AsyncInterfaces,但web.config中包含以下配置:
<dependentAssembly> <assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> </dependentAssembly>
类库代码如下:
public static void SetRecord(string recordId, string data, int minute = 30) { var redisConnection = Common.RedisCacheServiceClient(); IDatabase dbConnection = redisConnection.GetDatabase(); var timeSpan = TimeSpan.FromMinutes(minute); dbConnection.StringSet(recordId, data, timeSpan); }
该类库已安装Microsoft.Bcl.AsyncInterfaces 1.1.1和StackExchange.Redis 2.1.58,但程序执行到IDatabase dbConnection = redisConnection.GetDatabase();时抛出错误:
{"Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.":"Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51"}
项目中其他类库同样安装了Microsoft.Bcl.AsyncInterfaces 1.1.1,且app.config中包含相同的程序集绑定重定向配置,但运行正常。我有三个疑问:
- 为何Web API未安装该包却有相关引用?
- 为何其他类库可正常运行,我的类库却失败?
- 为何程序寻找的是6.0.0版本而非1.1.1版本?
1. 为何Web API未安装该包却有相关引用?
这个绑定重定向配置大概率是其他依赖该包的类库在编译/打包时自动注入到Web API的web.config里的。.NET Framework的NuGet包在安装时,如果项目是启动项目(比如你的Web API),会自动将依赖的程序集绑定重定向配置添加到web.config中——哪怕启动项目没直接装这个包,只要有引用的类库依赖它,就可能被自动加上。另外也有可能是手动修改web.config时添加上去的。
2. 为何其他类库可正常运行,我的类库却失败?
核心原因是你的Redis类库在执行GetDatabase()时,才触发了对Microsoft.Bcl.AsyncInterfaces的实际调用,而其他类库可能只是引用了该包但并没有执行到需要加载这个程序集的代码路径。比如有些类库可能只是声明了依赖,但实际运行时没走到用到异步接口的逻辑,所以不会触发程序集加载,自然不会报错。另外也可能是其他类库的绑定重定向在合并到web.config时生效逻辑不同,或者它们的代码路径没有触发StackExchange.Redis中需要Microsoft.Bcl.AsyncInterfaces的部分。
3. 为何程序寻找的是6.0.0版本而非1.1.1版本?
因为你的Web API的web.config里明确配置了绑定重定向,把所有0.0.0.0到6.0.0.0版本的Microsoft.Bcl.AsyncInterfaces都重定向到6.0.0.0版本。.NET Framework的程序集加载器会严格按照这个配置来查找对应的版本,而你的类库输出目录里只有1.1.1版本的dll,找不到6.0.0.0版本,所以抛出找不到文件的错误。
- 直接在Web API项目中安装Microsoft.Bcl.AsyncInterfaces 6.0.0版本的NuGet包,这样输出目录里就会有对应版本的dll,加载器能找到它。
- 修改web.config中的绑定重定向配置,把
newVersion改成你类库实际引用的1.1.1版本,比如:
<dependentAssembly> <assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="1.1.1.0" /> </dependentAssembly>
注意修改后要确保所有引用该包的类库都能兼容1.1.1版本(StackExchange.Redis2.1.58本身是支持1.1.1的)。
内容的提问来源于stack exchange,提问作者Psychonaut007

