培训
模块
创建新的 .NET 项目并使用包依赖项 - Training
创建 .NET 项目并了解如何在项目中添加包和管理包依赖项。 通过 Visual Studio Code 使用 .NET Core CLI 和 NuGet 注册表,向 C# 应用程序添加库和工具。
新式 .NET 项目与项目软件开发工具包 (SDK) 关联。 每个项目 SDK 都是一组 MSBuild 目标和相关的任务,它们负责编译、打包和发布代码。 引用项目 SDK 的项目有时称为“SDK 样式的项目”。
可用的 SDK 包括:
ID | 描述 | 存储库 |
---|---|---|
Microsoft.NET.Sdk |
.NET SDK | https://github.com/dotnet/sdk |
Microsoft.NET.Sdk.Web |
.NET Web SDK | https://github.com/dotnet/sdk |
Microsoft.NET.Sdk.Razor |
.NET Razor SDK | https://github.com/dotnet/aspnetcore |
Microsoft.NET.Sdk.BlazorWebAssembly |
The .NET Blazor WebAssembly SDK | https://github.com/dotnet/aspnetcore |
Microsoft.NET.Sdk.Worker |
.NET 辅助角色服务 SDK | https://github.com/dotnet/aspnetcore |
Aspire.AppHost.Sdk |
.NET Aspire SDK | https://github.com/dotnet/aspire |
MSTest.Sdk |
MSTest SDK | https://github.com/microsoft/testfx |
.NET SDK 是 .NET 的基本 SDK。 其他 SDK 引用 .NET SDK,与其他 SDK 关联的项目具有所有可用的 .NET SDK 属性。 例如,Web SDK 依赖于 .NET SDK 和 Razor SDK。
对于 Windows 窗体和 Windows Presentation Foundation (WPF) 项目,请指定 .NET SDK (Microsoft.NET.Sdk
),并在项目文件中设置一些其他属性。 有关详细信息,请参阅启用 .NET Desktop SDK。
MSBuild SDK(可用于配置和扩展生成)列在 MSBuild SDK 中。
你还可以创建自己的 SDK,并通过 NuGet 进行分发。
.NET 项目基于 MSBuild 格式。 具有扩展名(如用于 C# 项目的 .csproj 和用于 F# 项目的 .fsproj)的项目文件都是 XML 格式的 。 MSBuild 项目文件的根元素是 Project 元素。 Project
元素有一个可选的 Sdk
属性,该属性指定要使用的 SDK(和版本)。 若要使用 .NET 工具并构建你的代码,请将 Sdk
属性设置为可用 SDK 表中的其中一个 ID。
<Project Sdk="Microsoft.NET.Sdk">
<!-- Omitted for brevity... -->
</Project>
属性 Project/Sdk
和 Sdk
元素启用累加 SDK。 请考虑以下示例,其中 .NET Aspire SDK (Aspire.AppHost.Sdk
) 将添加到项目顶部 Microsoft.NET.Sdk
:
<Project Sdk="Microsoft.NET.Sdk">
<Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0" />
<!-- Omitted for brevity... -->
</Project>
在前面的项目文件中,这两个 SDK 用于解析具有累加性的依赖项。 有关详细信息,请参阅 .NET Aspire SDK
若要指定来自 NuGet 的 SDK,请在名称末尾包含版本,或者在 global.json 文件中指定名称和版本。
<Project Sdk="MSBuild.Sdk.Extras/2.0.54">
...
</Project>
另一种指定 SDK 的方法是使用顶层 Sdk
元素:
<Project>
<Sdk Name="Microsoft.NET.Sdk" />
...
</Project>
以这些方式之一引用 SDK 可以极大地简化 .NET 的项目文件。 在评估项目时,MSBuild 在项目文件的顶部和底部分别为 Sdk.props
和 Sdk.targets
添加隐式导入。
<Project>
<!-- Implicit top import -->
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
...
<!-- Implicit bottom import -->
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>
提示
在 Windows 计算机上,Sdk.props 和 Sdk.targets 文件位于 %ProgramFiles%\dotnet\sdk\[version]\Sdks\Microsoft.NET.Sdk\Sdk 文件夹中。
使用 dotnet msbuild -preprocess
命令,可以看到 MSBuild 在包含 SDK 及其目标之后所显示的完全扩展的项目。 dotnet msbuild
命令的预处理开关显示导入的文件、文件源及其在生成中的参与情况,而无需实际生成项目。
如果项目有多个目标框架,请将命令的结果指定为 MSBuild 属性,使其仅侧重于框架之一。 例如:
dotnet msbuild -property:TargetFramework=net8.0 -preprocess:output.xml
SDK 中定义了 Compile
项、嵌入的资源和 None
项默认包含和排除的内容。 与非 SDK .NET 框架项目不同,你无需在项目文件中指定这些项,因为默认设置涵盖了最常见的用例。 此行为使得项目文件更小、更易于理解和手动编辑(如需要)。
下表显示在 .NET SDK 中包含和排除的元素和 glob:
元素 | 包含 glob | 排除 glob | 删除 glob |
---|---|---|---|
Compile | **/*.cs(或其他语言扩展名) | **/*.user; **/*.*proj; **/*.sln; **/*.vssscc | 空值 |
EmbeddedResource | **/*.resx | **/*.user; **/*.*proj; **/*.sln; **/*.vssscc | 空值 |
None | **/* | **/*.user; **/*.*proj; **/*.sln; **/*.vssscc | **/*.cs; **/*.resx |
备注
默认情况下,由 $(BaseOutputPath)
和 $(BaseIntermediateOutputPath)
MSBuild 属性表示的 ./bin
和 ./obj
文件夹不包含在 glob 中。 排除由 DefaultItemExcludes 属性表示。
对于 WPF,.NET Desktop SDK 有更多包含和排除项。 有关详细信息,请参阅 WPF 默认包含和排除的内容。
如果在项目文件中显式定义这些项中的任何项,可能会出现 NETSDK1022 生成错误。 有关如何解决此错误的信息,请参阅 NETSDK1022:包含重复项。
从 .NET 6 开始,隐式 global using
指令将添加到新的 C# 项目中。 这意味着可以使用这些命名空间中定义的类型,而无需指定完全限定的名称或手动添加 using
指令。 隐式方面是指向项目的 obj 目录中生成的文件添加 global using
指令这一事实。
为使用以下 SDK 之一的项目添加隐式 global using
指令:
Microsoft.NET.Sdk
Microsoft.NET.Sdk.Web
Microsoft.NET.Sdk.Worker
Microsoft.NET.Sdk.WindowsDesktop
为基于项目 SDK 的一组默认命名空间中的每个命名空间添加 global using
指令。 下表显示了这些默认命名空间。
SDK 中 IsInRole 中的声明 | 默认命名空间 |
---|---|
Microsoft.NET.Sdk | System System.Collections.Generic System.IO System.Linq System.Net.Http System.Threading System.Threading.Tasks |
Microsoft.NET.Sdk.Web | Microsoft.NET.Sdk 命名空间 System.Net.Http.Json Microsoft.AspNetCore.Builder Microsoft.AspNetCore.Hosting Microsoft.AspNetCore.Http Microsoft.AspNetCore.Routing Microsoft.Extensions.Configuration Microsoft.Extensions.DependencyInjection Microsoft.Extensions.Hosting Microsoft.Extensions.Logging |
Microsoft.NET.Sdk.Worker | Microsoft.NET.Sdk 命名空间 Microsoft.Extensions.Configuration Microsoft.Extensions.DependencyInjection Microsoft.Extensions.Hosting Microsoft.Extensions.Logging |
Microsoft.NET.Sdk.WindowsDesktop(Windows 窗体) | Microsoft.NET.Sdk 命名空间 System.Drawing System.Windows.Forms |
Microsoft.NET.Sdk.WindowsDesktop (WPF) | Microsoft.NET.Sdk 命名空间 已删除 System.IO 已删除 System.Net.Http |
若要禁用此功能,或要在现有的 C# 项目中启用隐式 global using
指令,可通过 ImplicitUsings
MSBuild 属性实现。
可以通过向项目文件添加 Using
项(或针对 Visual Basic 项目添加 Import
项)来指定其他隐式 global using
指令,例如:
<ItemGroup>
<Using Include="System.IO.Pipes" />
</ItemGroup>
备注
从 .NET 8 SDK 开始, System.Net.Http 在面向 .NET Framework 时不再包含在Microsoft.NET.Sdk
其中。
如果你的项目以 .NET Standard 1.0-2.0 为目标,则 .NET SDK 会添加对某些元包的隐式引用。 元包是一种基于框架的包,其中只包含对其他包的依赖项。 元包根据项目文件的 TargetFramework 或 TargetFrameworks(复数)属性中指定的目标框架被隐式引用。
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
</PropertyGroup>
如果需要,可以使用 DisableImplicitFrameworkReferences 属性来禁用隐式包引用,并只添加对所需的框架或包的显式引用。
建议:
<PackageReference>
项添加对 NETStandard.Library
元包的显式引用。 对于 .NET Standard 1.0-2.0 项目,这些元包被隐式引用。 对于 .NET Framework 项目,如果在使用基于 .NET Standard 的 NuGet 包时需要任何版本的 NETStandard.Library
,则 NuGet 会自动安装相应版本。NETStandard.Library
元包,则可以使用 <NetStandardImplicitPackageVersion>
属性,并设置所需的版本。在 SDK 样式的项目中,请使用名为 PreBuild
或 PostBuild
的 MSBuild 目标,并设置 PreBuild
的 BeforeTargets
属性或 PostBuild
的 AfterTargets
属性。
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command=""$(ProjectDir)PreBuildEvent.bat" "$(ProjectDir)..\" "$(ProjectDir)" "$(TargetDir)"" />
</Target>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="echo Output written to $(TargetDir)" />
</Target>
备注
PreBuild
和 PostBuild
目标,因此通过使用这些名称,可以在 IDE 中编辑命令。PreBuildEvent
和 PostBuildEvent
,因为无法解析 $(ProjectDir)
这样的宏。 例如,以下代码是不受支持的:<PropertyGroup>
<PreBuildEvent>"$(ProjectDir)PreBuildEvent.bat" "$(ProjectDir)..\" "$(ProjectDir)" "$(TargetDir)"</PreBuildEvent>
</PropertyGroup>
可以通过多种方式自定义生成。 建议通过将属性作为参数传递给 msbuild 或 dotnet 命令来重写该属性。 还可以将属性添加到项目文件或 Directory.Build.props 文件中。 有关 .NET 项目的有用属性列表,请参阅 .NET SDK 项目的 MSBuild 参考。
提示
从命令行创建新的 Directory.Build.props 文件的一种简单方法是使用存储库根目录中的命令 dotnet new buildprops
。
.NET 项目可以打包自定义的 MSBuild 目标和属性,以供使用该包的项目使用。 如果要执行以下操作,请使用此类型的可扩展性:
通过在项目的生成文件夹中以 <package_id>.targets
或 <package_id>.props
(例如 Contoso.Utility.UsefulStuff.targets
)的形式放置文件,可以添加自定义生成目标或属性。
以下 XML 是 .csproj 文件中的一个片段,该文件指示 dotnet pack
命令打包的内容。 <ItemGroup Label="dotnet pack instructions">
元素将目标文件放入包内的生成文件夹中。 <Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles">
元素将程序集和 .json 文件放入生成文件夹 。
<Project Sdk="Microsoft.NET.Sdk">
...
<ItemGroup Label="dotnet pack instructions">
<Content Include="build\*.targets">
<Pack>true</Pack>
<PackagePath>build\</PackagePath>
</Content>
</ItemGroup>
<Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles">
<!-- Collect these items inside a target that runs after build but before packaging. -->
<ItemGroup>
<Content Include="$(OutputPath)\*.dll;$(OutputPath)\*.json">
<Pack>true</Pack>
<PackagePath>build\</PackagePath>
</Content>
</ItemGroup>
</Target>
...
</Project>
若要在项目中使用自定义目标,请添加指向包及其版本的 PackageReference
元素。 与工具不同,自定义目标包包含在消费项目的依赖项闭包中。
你可以配置自定义目标的使用方式。 由于它是 MSBuild 目标,因此会依赖于给定的目标并在另一个目标后运行,也可使用 dotnet msbuild -t:<target-name>
命令手动调用。 若要提供更好的用户体验,可以合并基于项目的工具和自定义目标。 在此方案中,每个项目工具接受所需的任何参数,并将其转换为执行目标所需的 dotnet msbuild
调用。 有关此类协同作用的示例,请访问 dotnet-packer
项目中的 2016 年编程马拉松 MVP 峰会示例存储库。
培训
模块
创建新的 .NET 项目并使用包依赖项 - Training
创建 .NET 项目并了解如何在项目中添加包和管理包依赖项。 通过 Visual Studio Code 使用 .NET Core CLI 和 NuGet 注册表,向 C# 应用程序添加库和工具。