[英]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.