SDK style 工程文件介绍
2024-04-18 21:36:38

SDK style 是一种新的项目文件格式。与传统的 .NET Framework 项目文件相比,新的 SDK style 提供了更简洁、可读性更好的语法,同时还引入了更多的灵活性和功能。
新风格的 csproj 文件是从 VS2017 版本开始引入和支持的。在 VS2015 和更早的版本,使用的是传统 csproj 文件格式。

新老工程文件

先看看老的工程文件是个什么样子。新建一个 .NET Framework 窗体项目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{013DB7AC-1A98-4BB9-8D01-C6CEA6C8AB78}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>WindowsFormsApp1</RootNamespace>
<AssemblyName>WindowsFormsApp1</AssemblyName>
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

再看看新的工程文件:

1
2
3
4
5
6
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework>
</PropertyGroup>
</Project>

高下立判,新风格的工程文件精简多了!

常用设置

OutputType

用于指定项目输出的文件类型。支持以下值:

说明
Library DLL 动态库
Exe 控制台程序
WinExe 窗口程序

TargetFramework

TargetFramework 用于指定项目的目标框架。它表示项目所针对的特定台或运行时环境。

1
2
3
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>

支持的值看这里:支持的目标框架
但是一般来说我们不应该指定这个值,而应该用复数版本的参数TargetFrameworks

TargetFrameworks

TargetFrameworks 允许针对多个不同的目标框架进行构建,每个目标框架通过分号进行分隔:

1
2
3
<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net462</TargetFrameworks>
</PropertyGroup>

这是必填的参数,指示工程使用哪些框架编译。

AppendTargetFrameworkToOutputPath

AppendTargetFrameworkToOutputPath 属性决定了输出路径中是否追加TargetFramework的值,默认为true

PlatformTarget

PlatformTarget 用于指定项目的目标平台。它决定了编译后的文件的实际架构。
可能的值:AnyCPUx86x64armarm64
来自 Microsoft.NET.RuntimeIdentifierInference.targets 文件中的片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!-- Determine PlatformTarget (if not already set) from runtime identifier. -->
<Choose>
<When Condition="'$(PlatformTarget)' != '' or '$(RuntimeIdentifier)' == ''" />

<When Condition="$(RuntimeIdentifier.EndsWith('-x86')) or $(RuntimeIdentifier.Contains('-x86-'))">
<PropertyGroup>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
</When>

<When Condition="$(RuntimeIdentifier.EndsWith('-x64')) or $(RuntimeIdentifier.Contains('-x64-'))">
<PropertyGroup>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
</When>

<When Condition="$(RuntimeIdentifier.EndsWith('-arm')) or $(RuntimeIdentifier.Contains('-arm-'))">
<PropertyGroup>
<PlatformTarget>arm</PlatformTarget>
</PropertyGroup>
</When>

<When Condition="$(RuntimeIdentifier.EndsWith('-arm64')) or $(RuntimeIdentifier.Contains('-arm64-'))">
<PropertyGroup>
<PlatformTarget>arm64</PlatformTarget>
</PropertyGroup>
</When>

<Otherwise>
<PropertyGroup>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
</Otherwise>
</Choose>

所以PlatformTarget不需要手动设置。

ImplicitUsings

ImplicitUsings 用于指定在项目代码中隐式引用的命名空间(using)。可以在项目中省略对特定命名空间的显式引用,从而简化代码。

1
2
3
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

UseWindowsForms

UseWindowsForms 属性设置为 true 时,项目将引用并使用 Windows Forms 库,以便开发 Windows Forms 应用程序。

1
2
3
<PropertyGroup>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>

UseWPF

UseWPF 属性设置为 true 时,项目将引用并使用 WPF 库,以便开发 WPF 程序。

1
2
3
<PropertyGroup>
<UseWPF>true</UseWPF>
</PropertyGroup>

RuntimeIdentifier

RID 是运行时标识符的缩写。 RID 值用于标识应用程序运行所在的目标平台。.NET 包使用它们来表示 NuGet 包中特定于平台的资产。
在编译时它会根据PlatformTarget属性自动设置,不需要手动设置。

AppendRuntimeIdentifierToOutputPath

AppendRuntimeIdentifierToOutputPath 属性决定了输出路径中是否追加RuntimeIdentifier的值,默认为true

Nullable

是否启用 可空类型 特性。

1
<Nullable>enable</Nullable>

打开 Nullable 设置可以提高代码的可读性、减少潜在的空引用异常,并帮助你编写更健壮和高质量的代码。

LangVersion

LangVersion 用于设置使用 C# 语言的版本。不设置时会有 默认值
原则上版本越高越好,毕竟使用新特性会使开发效率提高。

参考

常用的 MSBuild 项目属性
.NET 项目 SDK
.NET RID 目录
Platform vs. PlatformTarget In Any .NET Build