使用 Directory.Build 来消除项目文件中的重复配置
使用 Directory.Build 來消除項目文件中的重復配置
Intro
如果解決方案里的項目比較多的話,往往會有很多重復的項目屬性,通常我們可以使用獨立的 props 屬性文件來配置公用的屬性,而一般的屬性文件都需要手動的 Import 到項目文件中,而 MSBuild 支持自動導入我們要介紹的 Directory.Build.props中的配置,所以通常我們可以使用 Directory.Build.props 來減少項目中重復的屬性
DirectoryBuild
什么是 Directory.Build 呢?
Directory.Build 文件是放在某一個目錄下,其中的配置針對這個目錄下所有的項目都生效,并且 MSBuild 運行的時候會自動引入,不需要顯式地在項目文件中引入,主要分成 Directory.Build.props 和 Directory.Build.targets 兩類,在很多開源項目包括微軟的開源項目都有用到這個來簡化項目配置,.props 文件是屬性文件,通常定義公用的屬性,導入時機較早,項目中的定義可以覆蓋掉其中的配置,.targets 是目標文件,通常定義一些自定義的 MSBuild Task,導入時間稍后,可以用來覆蓋項目文件中的定義
通常我只是用到 Directory.Build.props 來配置公用的屬性
下面是一個項目文件中的一部分:
<Project?Sdk="Microsoft.NET.Sdk"><PropertyGroup><TargetFramework>net6.0</TargetFramework><LangVersion>latest</LangVersion><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings></PropertyGroup> </Project>上面 TargetFramwork/Nullable/ImplicitUsings 是一個 MSBuild 屬性,需要聲明在 PropertyGroup 內
如果一個解決方案中有很多個項目,那么這些可能就都是重復項了,這時候使用 Directory.Build.props 就會比較方便,比如說 ImplicitUsing 這一屬性,這個屬性是用來啟用 .NET 6 里的隱式命名空間引用的,但是從 .NET 6 RC1 默認是禁用的,需要顯式聲明 <ImplicitUsings>enable</ImplicitUsings> 來啟用,如果項目里的項目都是需要啟用的,那就可以直接聲明在 Directory.Build.props 中,放在項目根目錄下,如下所示:
<Project><PropertyGroup><LangVersion>latest</LangVersion><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings></PropertyGroup> </Project>除了 PropertyGroup 之外,我們也可以定義 <ItemGroup>,下面就是一個示例:
<Project><PropertyGroup><LangVersion>latest</LangVersion><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings></PropertyGroup><ItemGroup><Using?Include="WeihanLi.Common"/><Using?Include="WeihanLi.Common.Helpers"/><Using?Include="WeihanLi.Extensions"/></ItemGroup> </Project>這樣我們可以把公用的命名空間定義在 Directory.Build.props 上, MSBuild 會按目錄結構依次尋找上層的 Directory.Build.props,找到第一個之后就會停止再往上尋找,下面是一個示例
c:\users\username\code\test\case1 c:\users\username\code\test c:\users\username\code c:\users\username c:\users c:\如果項目較多可以使用多層 Directory.Build.props,下面是一個示例:
\MySolution.slnDirectory.Build.props?????(1)\srcDirectory.Build.props???(2-src)\Project1\Project2\testDirectory.Build.props???(2-test)\Project1Tests\Project2Tests所有項目 (1) 的通用屬性、src 項目 (2-src) 的通用屬性,以及 test 項目 (2-test) 的通用屬性
前面我們提到過,MSBuild 對于指定項目找到第一個 Directory.Build.props 就會停止再向上尋找 Directory.Build.props 如果要同時使用多級 Directory.Build.props 則需要顯式導入上層的 Directory.Build.props
<Import?Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props',?'$(MSBuildThisFileDirectory)../'))"?/>Sample
下面我們來看一些使用示例吧
Sample1
在稍微復雜一些項目,往往會引用很多的 Nuget 包,而一些項目的版本可能是有關系的,有些包的版本是一致的,此時我們可以考慮定義一個屬性,而在包版本的地方則引用這個屬性
項目根目錄下 Directory.Build.props 內容
<PropertyGroup><LangVersion>latest</LangVersion><Nullable>enable</Nullable><EFVersion>6.0.0-rc.1.*</EFVersion> </PropertyGroup>項目文件中內容:
<ItemGroup><PackageReference?Include="Microsoft.EntityFrameworkCore.SqlServer"?Version="$(EFVersion)"?/><PackageReference?Include="Microsoft.EntityFrameworkCore.Sqlite"?Version="$(EFVersion)"?/><PackageReference?Include="Microsoft.EntityFrameworkCore.InMemory"?Version="$(EFVersion)"?/> </ItemGroup>這樣我們如果需要更新 EF 的版本,我們只需要更新 Directory.Build.props 文件中的 EFVersion 這個屬性就可以了,詳細配置可以參考:https://github.com/WeihanLi/WeihanLi.EntityFramework
Sample2
我們再來看一個多個層級使用的示例,項目結構如下所示:
Directory.Build.props --src --tests --Directory.Build.props ----UnitTest ----IntegrationTest項目根目錄下 Directory.Build.props,主要定義 package 相同的屬性配置以及啟用可控引用類型,隱式命名空間和公用的命名空間
tests 目錄下 Directory.Build.props,定義了測試項目公用的命名空間,并引入了上一層 Directory.Build.props 中的屬性
<Project><Import?Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props',?'$(MSBuildThisFileDirectory)../'))"?/><ItemGroup><Using?Include="FluentAssertions"/><Using?Include="Xunit"/></ItemGroup> </Project>IntegrationTest 項目文件,引入自己需要的命名空間引用
<ItemGroup><Using?Include="HTTPie"/><Using?Include="HTTPie.Implement"/><Using?Include="HTTPie.Middleware"/><Using?Include="HTTPie.Models"/><Using?Include="HTTPie.Utilities"/> </ItemGroup>具體配置可以參考:https://github.com/WeihanLi/dotnet-httpie
More
使用好 Directory.Build.props 可以簡化項目配置,使得項目更容易維護,如果還沒用起來的可以嘗試一下哈
References
https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?WT.mc_id=DT-MVP-5004222&view=vs-2019
https://github.com/WeihanLi/SparkTodo/blob/master/Directory.Build.props
https://github.com/WeihanLi/SamplesInPractice/tree/master/net6sample
https://github.com/WeihanLi/WeihanLi.EntityFramework/blob/dev/Directory.Build.props
https://github.com/WeihanLi/dotnet-httpie/blob/dev/Directory.Build.props
https://github.com/WeihanLi/dotnet-httpie/blob/dev/tests/Directory.Build.props
總結
以上是生活随笔為你收集整理的使用 Directory.Build 来消除项目文件中的重复配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 志愿者招募 | 2021 .NET Co
- 下一篇: 技术分享 | 业务模板的技术实践