已连接项目组的 MSBuild 元数据

发布于 2024-10-13 04:11:58 字数 621 浏览 7 评论 0原文

我希望加入两个项目组:

  <ItemGroup>
<ServerTypeA Include="ServerA;ServerB;">
  <MetaDataA>A</MetaDataA>
</ServerTypeA>
</ItemGroup>

  <ItemGroup>
<ServerTypeB Include="ServerB;ServerC;">
  <MetaDataB>B</MetaDataB>
</ServerTypeB>
</ItemGroup>

使用常规联接将为我提供一个包含 4 个项目的集合:

ServerA with Metadata A;
ServerB with Metadata A;
ServerB with Metadata B;
ServerC with Metadata B;

如何创建以下集合:

ServerA with Metadata A
ServerB with Metadata A & B
ServerC with Metadata B

I have two item groups that I wish to join:

  <ItemGroup>
<ServerTypeA Include="ServerA;ServerB;">
  <MetaDataA>A</MetaDataA>
</ServerTypeA>
</ItemGroup>

  <ItemGroup>
<ServerTypeB Include="ServerB;ServerC;">
  <MetaDataB>B</MetaDataB>
</ServerTypeB>
</ItemGroup>

Using the regular join will give me a collection with 4 items:

ServerA with Metadata A;
ServerB with Metadata A;
ServerB with Metadata B;
ServerC with Metadata B;

How can I create the following collection:

ServerA with Metadata A
ServerB with Metadata A & B
ServerC with Metadata B

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

森林散布 2024-10-20 04:11:58

这是有可能的。您必须可以手动执行连接。

以下是如何执行此操作的示例(需要 msbuild 3.5 或更高版本):

<ItemGroup>
  <ServerTypeA Include="ServerA;ServerB;">
    <MetaDataA>A</MetaDataA>
  </ServerTypeA>

  <ServerTypeB Include="ServerB;ServerC;">
    <MetaDataB>B</MetaDataB>
  </ServerTypeB>
</ItemGroup>

<Target Name="JoinServers" DependsOnTargets="ProcessServerTypeA;ProcessServerTypeB">
  <Message Text="%(Joined.Identity) Metadata: %(Joined.MetaDataA)%(Joined.MetaDataB)"/>
</Target>

<!--Create -->
<Target Name="ProcessServerTypeA">
  <ItemGroup>
    <Joined Include="%(ServerTypeA.Identity)">
      <MetaDataA>%(ServerTypeA.MetaDataA)</MetaDataA>
    </Joined>
  </ItemGroup>
</Target>

<!--Need to batch at the target level for this to work-->
<Target Name="ProcessServerTypeB" Inputs="@(ServerTypeB)" Outputs="%(ServerTypeB.Identity)'">

  <PropertyGroup>
    <!--Create Temporary Properties for the Item Metadata-->
    <TempItemName>%(ServerTypeB.Identity)</TempItemName>
    <TempMetaDataB>%(ServerTypeB.MetaDataB)</TempMetaDataB>
    <!--Does the current item already exist?-->
    <TempIsDuplicate Condition="'%(Joined.Identity)' == '$(TempItemName)'">True</TempIsDuplicate>
  </PropertyGroup>

  <ItemGroup>
    <!--Update the existing item's metadata if this is a duplicate-->
    <!--Don't provide the include attribute.  This will allow you to update existing items metadata-->
    <!--Have to reference %(Joined.Identity) in the condtion to ensure we only update the correct item-->
    <!--You cannot directly reference metadata from ServerTypeB here.  Hence the need for the temp Properties-->
    <Joined Condition="'%(Joined.Identity)' == '$(TempItemName)'">
      <MetaDataB>$(TempMetaDataB)</MetaDataB>
    </Joined>

    <!--Create a new item if current item is not a duplicate-->
    <Joined Include="$(TempItemName)" Condition="'$(TempIsDuplicate)' != 'True'">
      <MetaDataB>$(TempMetaDataB)</MetaDataB>
    </Joined>
  </ItemGroup>
</Target>

运行 JoinServers 目标将产生以下输出:

ServerA Metadata: A
ServerB Metadata: AB
ServerC Metadata: B

使用更好的答案更新

这个问题向我指出了一个更简单的解决方案。

基本上,您使用 转换修饰符%(Identity) 执行连接。

您可以将上面的所有 3 个目标替换为以下目标以获得相同的输出。

<Target Name="JoinServers">
  <ItemGroup>
    <Joined Include="%(Identity)">
      <MetaDataA>@(ServerTypeA->'%(MetaDataA)')</MetaDataA>
      <MetaDataB>@(ServerTypeB->'%(MetaDataB)')</MetaDataB>
    </Joined>
  </ItemGroup>

  <Message Text="%(Joined.Identity) Metadata: %(Joined.MetaDataA)%(Joined.MetaDataB)"/>
</Target>

It's possible. You have to can manually perform the join.

Here's an example of how to do it (msbuild 3.5 or greater required):

<ItemGroup>
  <ServerTypeA Include="ServerA;ServerB;">
    <MetaDataA>A</MetaDataA>
  </ServerTypeA>

  <ServerTypeB Include="ServerB;ServerC;">
    <MetaDataB>B</MetaDataB>
  </ServerTypeB>
</ItemGroup>

<Target Name="JoinServers" DependsOnTargets="ProcessServerTypeA;ProcessServerTypeB">
  <Message Text="%(Joined.Identity) Metadata: %(Joined.MetaDataA)%(Joined.MetaDataB)"/>
</Target>

<!--Create -->
<Target Name="ProcessServerTypeA">
  <ItemGroup>
    <Joined Include="%(ServerTypeA.Identity)">
      <MetaDataA>%(ServerTypeA.MetaDataA)</MetaDataA>
    </Joined>
  </ItemGroup>
</Target>

<!--Need to batch at the target level for this to work-->
<Target Name="ProcessServerTypeB" Inputs="@(ServerTypeB)" Outputs="%(ServerTypeB.Identity)'">

  <PropertyGroup>
    <!--Create Temporary Properties for the Item Metadata-->
    <TempItemName>%(ServerTypeB.Identity)</TempItemName>
    <TempMetaDataB>%(ServerTypeB.MetaDataB)</TempMetaDataB>
    <!--Does the current item already exist?-->
    <TempIsDuplicate Condition="'%(Joined.Identity)' == '$(TempItemName)'">True</TempIsDuplicate>
  </PropertyGroup>

  <ItemGroup>
    <!--Update the existing item's metadata if this is a duplicate-->
    <!--Don't provide the include attribute.  This will allow you to update existing items metadata-->
    <!--Have to reference %(Joined.Identity) in the condtion to ensure we only update the correct item-->
    <!--You cannot directly reference metadata from ServerTypeB here.  Hence the need for the temp Properties-->
    <Joined Condition="'%(Joined.Identity)' == '$(TempItemName)'">
      <MetaDataB>$(TempMetaDataB)</MetaDataB>
    </Joined>

    <!--Create a new item if current item is not a duplicate-->
    <Joined Include="$(TempItemName)" Condition="'$(TempIsDuplicate)' != 'True'">
      <MetaDataB>$(TempMetaDataB)</MetaDataB>
    </Joined>
  </ItemGroup>
</Target>

Running the JoinServers target will produce the following output:

ServerA Metadata: A
ServerB Metadata: AB
ServerC Metadata: B

Update with a better answer

This question pointed me to a much simpler solution.

Basically you use Transform modifiers with %(Identity) to perform the join.

You can replace all 3 targets from above with the following to obtain the same output.

<Target Name="JoinServers">
  <ItemGroup>
    <Joined Include="%(Identity)">
      <MetaDataA>@(ServerTypeA->'%(MetaDataA)')</MetaDataA>
      <MetaDataB>@(ServerTypeB->'%(MetaDataB)')</MetaDataB>
    </Joined>
  </ItemGroup>

  <Message Text="%(Joined.Identity) Metadata: %(Joined.MetaDataA)%(Joined.MetaDataB)"/>
</Target>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文