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
用于指定项目的目标平台。它决定了编译后的文件的实际架构。
可能的值:AnyCPU
、x86
、x64
、arm
、arm64
。
来自 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
| <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 属性设置为 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