繁体   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