[英]Disable transitive project reference in .NET Standard 2
我正在使用 ASP.NET Core 2.0 編寫一個 MVC 網站。
在 ASP.NET Core 項目(我們稱之為Web
)中,我在同一個解決方案中引用了一個 .NET Standard 2 項目(我們稱之為Service
)。 Service
項目還引用了解決方案中的第三個 .NET Standard 2 庫(我們稱之為Business
)。 Business
項目聲明了一個名為Model
的類型。
問題是我可以在Web
項目中使用Model
(即編譯器看到類型Model
並且我可以執行var a = new Model();
),就好像Web
項目引用了Business
,但它實際上只引用了Service
。
如何從Web
隱藏Model
? 這是 ASP.NET Core 2 中的新功能還是所有 .NET Standard 項目都是這樣?
編輯
如此處所述,這是由於傳遞項目引用造成的,這是 .NET Standard 中的一項新“功能”,但我該如何解決?
ProjectReference
)可傳遞項目引用是 .NET Core/.NET >= 5 中使用的 SDK 樣式 csproj ( 1 , 2 ) 格式的新功能。您也可以將此 csproj 用於舊的 .NET Framework 項目( 1 、 2 、 3 ),但使用一些例外。
在此 SDK 樣式格式中,項目引用(由 .csproj 文件中的<ProjectReference>
條目表示)是可傳遞的。 這與之前使用的舊的非 SDK .csproj 不同。
但是你有三個選項可以回到舊的非傳遞行為。
在 .csproj 中使用<DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>
屬性來引用您不希望編譯器可見其傳遞依賴項的項目。
在您的情況下,您可以將其添加到Web項目中。 (第一個引用其他項目的項目, Web -> Service -> Business )
您還可以通過在放置在包含源的根文件夾中的Directory.Build.props文件中為所有 .csprojs 全局設置此行為。
<Project> <PropertyGroup> <DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences> </PropertyGroup> </Project>
使用此文件,您基本上擁有舊的項目參考行為。 當您將使用舊 csproj 格式的舊 .NET Framework 解決方案遷移到新的 SDK 樣式 .csprojs 時很有用。
在您引用的項目上,您可以設置在引用該項目時哪些依賴項不應進一步流動。 為此,您可以在<ProjectReference>
上使用PrivateAssets="All"
屬性。 例如,您可以像這樣編輯Service .csproj:
<ItemGroup> <ProjectReference Include="..\\Business.csproj" PrivateAssets="All" /> </ItemGroup>
這是一種更靈活和細粒度的方法。 當項目被引用時,您可以控制特定的可傳遞項目引用應該是可見的。
使用ItemDefinitionGroup
為所有ProjectReference
定義默認的<PrivateAssets>all</PrivateAssets>
元數據。 如果要將其全局應用於所有項目,也可以在Directory.Build.props文件中定義它。
<ItemDefinitionGroup> <ProjectReference> <PrivateAssets>all</PrivateAssets> </ProjectReference> </ItemDefinitionGroup>
效果與設置<ProjectReference Include="..."> <PrivateAssets>All</PrivateAssets> </ProjectReference>
(或所有ProjectReferences
條目的PrivateAssets="All"
屬性)相同。
與使用 1. 方法 ( DisableTransitiveProjectReferences
) 的不同之處在於,如果您在ProjectReference
項上明確定義PrivateAssets
元數據,則使用此值。 您可以將ItemDefinitionGroup
視為提供PrivateAssets
元數據默認值的一種方式,它沒有明確提供。
你應該用什么? 這取決於你喜歡什么。 如果您習慣了舊的 csproj 行為或想要將舊的解決方案遷移到 .NET Core,那么在Directory.Build.props 中使用DisableTransitiveProjectReferences
或ItemDefinitionGroup
是最簡單的解決方案。
PackageReference
) 也是可傳遞的。這不是嚴格回答您的問題,而是您也應該注意的事情。
如果您對 nuget 包使用新的PackageReference
格式(您可能會這樣做,因為這是新的 SDK 樣式的 csproj 文件中的默認格式),那么您還應該注意這些引用是可傳遞的。 如果您的項目引用另一個引用 nuget 包(帶有PackageReference
)的項目(帶有ProjectReference
),那么您的項目也將引用此 nuget 包。
這里ProjectA將隱式引用Newtosoft.Json庫。
不幸的是,沒有用於包引用的DisableTransitivePackagesReferences 。 但是您可以像在第二個選項中為ProjectReference
所做的那樣使用PrivateAssets元數據,或者像在第三個選項中那樣使用ItemDefinitionGroup
。
這就是為什么如果要禁用所有項目的項目和包引用的傳遞依賴項,那么Directory.build.props文件應如下所示:
<Project>
<ItemDefinitionGroup>
<PackageReference>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<ProjectReference>
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
</ItemDefinitionGroup>
</Project>
(來源:我從這個博客中了解到了這項技術)
以上所有答案目前都不適用於 nuget 包依賴項。
對於以下庫項目 (PrivateAssets="all"):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Roy</Authors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" PrivateAssets="all" />
</ItemGroup>
</Project>
將生成以下 nuspec 文件:
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>MyLib</id>
<version>1.0.0</version>
<authors>Roy</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package Description</description>
<dependencies>
<group targetFramework=".NETStandard2.0" />
</dependencies>
</metadata>
</package>
請注意“Newtonsoft.Json”甚至沒有被指定為依賴項。 這顯然不起作用,因為 Visual Studio 甚至不會意識到這種依賴關系,並且使用項目將無法在運行時解析“Newtonsoft.Json”。
正確答案是設置PrivateAssets="compile"
。
這將產生以下 nuspec 文件:
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>MyLib</id>
<version>1.0.0</version>
<authors>Roy</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package Description</description>
<dependencies>
<group targetFramework=".NETStandard2.0">
<dependency id="Newtonsoft.Json" version="13.0.1" include="Runtime,Build,Native,ContentFiles,Analyzers,BuildTransitive" />
</group>
</dependencies>
</metadata>
</package>
這將阻止消費項目在代碼中訪問 Newtonsoft.Json 命名空間,同時編譯和復制所有必需的程序集以允許“封裝”庫工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.