VS2017项目引用链中Iesi.Collections.dll丢失致运行时错误求助
这个问题我之前也碰到过几次,本质上是Visual Studio的依赖传递优化和NuGet包依赖处理的“小坑”——当间接依赖的程序集没有被上层项目直接使用时,VS的构建系统会默认跳过复制,导致运行时找不到dll。下面给你几个靠谱的解决办法,不用破坏你的关注点分离原则:
1. 确保Project A的依赖引用配置正确
先回到Project A里,找到Iesi.Collections.dll的引用,右键查看属性:
- 确认
Copy Local是True(对应csproj里的<Private>True</Private>),这个设置是让VS知道这个dll需要被复制到引用A的项目输出目录。 - 另外,检查这个引用是通过NuGet添加的(而非手动拷贝的dll),并且在Project A的csproj里,这个NuGet包的引用没有设置限制依赖传递的属性。比如确保配置类似这样:
<PackageReference Include="Iesi.Collections" Version="x.x.x"> <IncludeAssets>all</IncludeAssets> <PrivateAssets>none</PrivateAssets> </PackageReference>
PrivateAssets>none会让这个包的依赖可以被传递到引用A的项目(比如B和C)。
2. 强制Project B保留传递依赖
因为Project B没有直接使用Iesi.Collections的类型,VS可能会“聪明过头”,把这个间接依赖从传递给C的列表里移除。这时候可以在Project B的csproj里,对Project A的引用添加属性,确保A的所有依赖都能传递给C:
<ProjectReference Include="..\ProjectA\ProjectA.csproj"> <PrivateAssets>none</PrivateAssets> </ProjectReference>
这个设置会告诉VS:把Project A的所有私有资产(包括它的依赖dll)都传递给引用B的项目(也就是C)。
3. 用MSBuild属性强制复制所有锁定的NuGet依赖
如果上面的方法都不行,可以在Project C的csproj文件里添加一个全局设置,强制复制所有NuGet锁定文件里的依赖到输出目录:
<PropertyGroup> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> </PropertyGroup>
这个属性会让VS忽略“是否直接使用”的判断,把所有通过NuGet还原的依赖(包括间接的)都复制到C的bin目录里,完美符合你“C不需要了解A的依赖”的需求。
4. 清理重建+NuGet还原
有时候VS的缓存或者旧的输出文件会干扰依赖传递,按下面的步骤操作:
- 右键解决方案,选择“清理解决方案”
- 删除所有项目的
bin和obj目录(手动删除更彻底) - 右键解决方案,选择“还原NuGet包”
- 最后重新“生成解决方案”
为什么会出现这个问题?因为Visual Studio的构建系统有一个“未使用引用优化”:如果一个程序集(比如Iesi.Collections.dll)没有被当前项目(B)的代码直接引用,VS会默认不把它复制到上层项目(C)的输出目录,哪怕它是下层项目(A)的必需依赖。而上面的方法都是通过调整依赖传递的规则,或者强制复制,来绕过这个优化。
内容的提问来源于stack exchange,提问作者Neil Humby

