微軟近幾年推出.NET Standard,將.NET Framework,.NET Core,Xamarin等目標平台的api進行標准化和統一化,極大地方便了類庫編寫人員的工作。簡單的說,類庫編寫人員在發布庫的時候,只需要基於.NET Standard進行發布,那么編寫的程序可以在各個目標平台上都能到運行。
.NET Standard是一種標准,只要符合這個標准的平台都可以運行基於此標准api構建的程序。
感覺挺好用的,但是實際上用起來就有一些坑了。比如說這個常見的FileNotFoundException,當有這個情況的時候,經常出現:
主程序的目標平台是某個具體平台(不是.NET Standard,比如說是.NET Framework 4.0),隨后為了引入新的特性,升級了Framework為4.6.1,它並且引用了一個.NET Standard類庫,恰好,這個類庫還引用了其他的package。(即傳遞引用A->B->C的形式,其中A是.NET Framework程序,B是nuget包,C是B引用的nuget包。)在此情況下,如果F5啟動程序,就會報FileNotFoundException。
測試條件
Visual Studio 2015 Community
測試用包:UnifiedConfig v1.1.6
提示未找到System.IO.FileSystem。乍看感覺是一個簡單的引用錯誤,但unifiedconfig包里面已經正常引用了這個項目,按道理vs能夠正常幫我們處理引用問題。到文件輸出路徑中查看,發現對應的包沒有正確復制過來。手動從package文件夾中復制過來,問題解決。
原因出在這個跨平台上。由於存在引用傳遞,B不能確定需要復制哪個目標平台的package到A的輸出路徑。當程序是從舊的Framework升級而來的時候,舊版的項目文件不能很好地處理.NET Standard的這個問題。但我們手動一個一個復制也不是辦法,以下給出解決方案。
解決方案:
- 最直接的方案,修改主項目的.csproj文件,將
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>添加到第一個PropertyGroup - 如果還不行,加上
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
或者
- 在工具->nuget包管理器->程序包管理->默認包管理格式,從Packages.config改成PackageReference。
后記
我記得在visual studio 2017早期版本還存在這個bug,升級之后visual studio 2017 15.6.4這個版本測試新建項目,已經沒有這個問題。並且默認生成的基於4.5.2以上Framework的.csproj文件已經添加<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>這個配置。但是當老版本的項目引用.NET Standard類庫的時候,還是經常會出現這個問題,這時候,就需要我們手動添加配置項目了。
