簡體   English   中英

在 .NET Standard 2 中禁用可傳遞項目引用

[英]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 中的一項新“功能”,但我該如何解決?

好吧,我的問題接近於此處標記為重復的問題,但要解決它需要不同的策略。

感謝“Federico Dipuma”的評論和這里給出的答案我能夠解決這個問題。

您應該編輯Service.csproj文件並將PrivateAssets="All"添加到您不想流到頂部的ProjectReference鍵。

<ItemGroup>
    <ProjectReference Include="..\Business.csproj" PrivateAssets="All" />
</ItemGroup>

可傳遞項目引用 ( ProjectReference )

可傳遞項目引用是 .NET Core/.NET >= 5 中使用的 SDK 樣式 csproj ( 1 , 2 ) 格式的新功能。您也可以將此 csproj 用於舊的 .NET Framework 項目( 123 ),但使用一些例外

在此 SDK 樣式格式中,項目引用(由 .csproj 文件中的<ProjectReference>條目表示)是可傳遞的。 這與之前使用的舊的非 SDK .csproj 不同。

但是你有三個選項可以回到舊的非傳遞行為。

  1. 在 .csproj 中使用<DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>屬性來引用您不希望編譯器可見其傳遞依賴項的項目。

    在您的情況下,您可以將其添加到Web項目中。 (第一個引用其他項目的項目, Web -> Service -> Business

    您還可以通過在放置在包含源的根文件夾中的Directory.Build.props文件中為所有 .csprojs 全局設置此行為。

     <Project> <PropertyGroup> <DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences> </PropertyGroup> </Project>

    使用此文件,您基本上擁有舊的項目參考行為。 當您將使用舊 csproj 格式的舊 .NET Framework 解決方案遷移到新的 SDK 樣式 .csprojs 時很有用。

  2. 在您引用的項目上,您可以設置在引用該項目時哪些依賴項不應進一步流動 為此,您可以在<ProjectReference>上使用PrivateAssets="All"屬性。 例如,您可以像這樣編輯Service .csproj:

     <ItemGroup> <ProjectReference Include="..\\Business.csproj" PrivateAssets="All" /> </ItemGroup>

    這是一種更靈活和細粒度的方法。 當項目被引用時,您可以控制特定的可傳遞項目引用應該是可見的。

  3. 使用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 中使用DisableTransitiveProjectReferencesItemDefinitionGroup是最簡單的解決方案。


默認情況下,Nuget 引用 ( PackageReference ) 也是可傳遞的。

這不是嚴格回答您的問題,而是您也應該注意的事情。

如果您對 nuget 包使用新的PackageReference格式(您可能會這樣做,因為這是新的 SDK 樣式的 csproj 文件中的默認格式),那么您還應該注意這些引用是可傳遞的。 如果您的項目引用另一個引用 nuget 包(帶有PackageReference )的項目(帶有ProjectReference ),那么您的項目也將引用此 nuget 包。

顯示 ProjectA 引用 ProjectB 的圖表,該 ProjectB 引用了 Newtonsoft.Jon 包

這里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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM