mcpField
P
property-patterns

property-patterns

github.com/dotnet开发5.8k3.2k 次安装1 天前更新
代码仓库

关于 property-patterns

记录 MSBuild 属性规范模式的参考 Skill,涵盖默认值、条件、组合、路径和求值顺序,适用于维护 MSBuild 项目文件。

主要功能

  1. 01可覆盖的条件默认值
  2. 02嵌套条件属性组
  3. 03以分号组合属性
  4. 04路径规范化模式
  5. 05目标框架与版本保护条件
  6. 06求值顺序和回退指南

适用场景

  1. 01定义可由调用方覆盖的默认值
  2. 02安全追加常量或警告代码
  3. 03规范化项目文件中的路径

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dotnet/skills --skill property-patterns

安装后在 Claude Code 中输入/property-patterns确认已加载。

详细介绍

MSBuild 属性模式

MSBuild 仓库中的规范属性定义和操作模式。

条件默认值——基础模式

仅当属性尚未设置时才设置,允许调用方覆盖:

<PropertyGroup>
  <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
  <Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
  <BuildInParallel Condition="'$(BuildInParallel)' == ''">true</BuildInParallel>
</PropertyGroup>
规则
  • 两侧始终加引号:'$(Prop)' == ''
  • 在 .props 中:创建可覆盖的默认值。在 .targets 中:创建回退值。
  • 不带条件的属性无法被较早导入的内容覆盖。

嵌套条件组

在共享条件下对相关属性进行分组:

<PropertyGroup Condition="$(TargetFramework.StartsWith('net4'))">
  <DefineConstants>$(DefineConstants);FEATURE_APARTMENT_STATE</DefineConstants>
  <DefineConstants>$(DefineConstants);FEATURE_APM</DefineConstants>
  <FeatureAppDomain>true</FeatureAppDomain>
</PropertyGroup>

<PropertyGroup Condition="'$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)'))' == '.NETCoreApp'">
  <NetCoreBuild>true</NetCoreBuild>
  <DefineConstants>$(DefineConstants);RUNTIME_TYPE_NETCORE</DefineConstants>
</PropertyGroup>

在 PropertyGroup 上使用外层 Condition,避免在每个属性上重复相同的条件。

警告: 对于单目标项目,在项目主体求值之前,$(TargetFramework) 在 .props 文件中为空。请将以 TargetFramework 为条件的属性组放在 .targets 文件(或项目文件本身)中,此时该值始终可用。

组合——分号拼接

保存列表的属性使用分号。追加时始终包含现有值:

<PropertyGroup>
  <DefineConstants>$(DefineConstants);MY_FEATURE</DefineConstants>
  <NoWarn>$(NoWarn);NU5131;IDE0005</NoWarn>
  <LibraryTargetFrameworks>$(FullFrameworkTFM);$(LatestDotNetCoreForMSBuild);netstandard2.0</LibraryTargetFrameworks>
</PropertyGroup>

路径规范化和尾随斜杠


<PropertyGroup>
  <OutDir Condition="'$(OutDir)' != '' and !HasTrailingSlash('$(OutDir)')">$(OutDir)\</OutDir>
</PropertyGroup>


<PropertyGroup>
  <TargetRefPath>$([MSBuild]::NormalizePath('$(TargetDir)', 'ref', '$(TargetFileName)'))</TargetRefPath>
</PropertyGroup>


<PropertyGroup>
  <MSBuildProjectExtensionsPath
      Condition="'$([System.IO.Path]::IsPathRooted('$(MSBuildProjectExtensionsPath)'))' == 'false'">
    $([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(MSBuildProjectExtensionsPath)'))
  </MSBuildProjectExtensionsPath>
</PropertyGroup>
首选路径函数
函数用途
$([MSBuild]::NormalizePath(...))合并并规范化(跨平台)
$([System.IO.Path]::Combine(...))合并路径片段
$([System.IO.Path]::IsPathRooted(...))检查是否为绝对路径
HasTrailingSlash(...)检查是否有尾随斜杠
$([MSBuild]::GetDirectoryNameOfFileAbove(...))向上遍历目录树
$(MSBuildThisFileDirectory)当前文件所在目录

目标框架检测辅助项


<PropertyGroup Condition="'$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)'))' == '.NETCoreApp'">
  <NetCoreBuild>true</NetCoreBuild>
</PropertyGroup>


<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net472'))">
  <UseFrozenVersions>true</UseFrozenVersions>
</PropertyGroup>


<PropertyGroup Condition="$([MSBuild]::IsOSPlatform('windows'))">
  <DefineConstants>$(DefineConstants);TEST_ISWINDOWS</DefineConstants>
</PropertyGroup>

守卫属性

标记文件已导入,以防止重复导入:


<PropertyGroup>
  <MySDKPropsImported>true</MySDKPropsImported>
</PropertyGroup>


<Import Project="MySDK.props" Condition="'$(MySDKPropsImported)' != 'true'" />

按 MSBuild 版本控制功能

<PropertyGroup Condition="$([MSBuild]::AreFeaturesEnabled('17.10'))">
  <UseNewBehavior>true</UseNewBehavior>
</PropertyGroup>

回退链

先通过主要来源设置,然后再回退:

<PropertyGroup>
  <TlbExpPath>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToDotNetFrameworkSdkFile('tlbexp.exe'))</TlbExpPath>
  <TlbExpPath Condition="'$(TlbExpPath)' == ''">$(_NetFxToolsDir)TlbExp.exe</TlbExpPath>
</PropertyGroup>

后写入者生效——求值顺序

MSBuild 按从上到下的顺序对属性求值。最后一次赋值生效:


<MyProp>value1</MyProp>        

<MyProp>value2</MyProp>        

<MyProp Condition="'$(MyProp)' == ''">value3</MyProp>  

.targets 中的属性(较晚导入)会覆盖 .props 中的属性(较早导入)和项目文件中的属性。

常见问题

  • 条件未加引号($(X)==true)在属性为空时会失败。两侧始终加引号。
  • 覆盖 DefineConstants(<DefineConstants>MY_CONST</DefineConstants>)会丢弃所有先前的常量。始终使用 $(DefineConstants); 追加。
  • 硬编码绝对路径会破坏可移植性。请使用 $(MSBuildThisFileDirectory) 或 $([MSBuild]::NormalizePath(...))。
  • 默认值缺少 Condition 会使属性无法覆盖。对于作为默认值的属性,请添加 Condition="'$(Prop)' == ''"。

评论

支持 Markdown