6

プロジェクト ファイル コレクションがあります。

<ItemGroup>
  <ApplicationToDeploy
    Include="Frontend.WebSite.csproj;11.WebServices.csproj;22.WebServices.csproj"/>
  <ApplicationToDeploy
    Include="33.WebServices.csproj;44.WebServices.csproj;Workflow55Svc.csproj"/>
</ItemGroup>

これらのプロジェクトの .config ファイルのコレクションを取得しようとしています:

<Target Name="111">
  <PropertyGroup>
    <Cfgs>@(ApplicationToDeploy->'%(RootDir)%(Directory)*.config')</Cfgs>
  </PropertyGroup>

  <ItemGroup>
    <InputConfigs Include="$(Cfgs)" />
  </ItemGroup>

  <Message Text="Cfgs: @(InputConfigs)"/>
</Target>

Targetブロック内ではすべて正常に動作します (Web.Configs、App.Configs、Log4net.Configs などのコレクションが表示されます):

Cfgs: C:\Sources\WebServices\11\WebServices\11.WebServices\Web.config;C:\Sources\WebServices\22\WebServices\22.WebServices\web.log4net.config;C:\Sources\WebServices\33\WebServices\33.WebServices\web.environment.config

しかし、このItemGroupをTargetブロックの外で初期化したいと考えています。このような:

<PropertyGroup>
  <Cfgs>@(ApplicationToDeploy->'%(RootDir)%(Directory)*.config')</Cfgs>
</PropertyGroup>

<ItemGroup>
  <InputConfigs Include="$(Cfgs)" />
</ItemGroup>

<Target Name="111">
  <Message Text="Cfgs: @(InputConfigs)"/>
</Target>

Target ブロックの外でこれを行うと、次のようになります。

Cfgs: C:\Sources\WebServices\11\WebServices\11.WebServices\*.config;C:\Sources\WebServices\22\WebServices\22.WebServices\*.config;C:\Sources\WebServices\33\WebServices\33.WebServices\*.config

何が起こっているのか理解できません。Targetブロックの外で同じ結果を得ることができますか?

4

1 に答える 1

6

何が起こっているのか理解できません。

この動作は、MSBuild の評価順序の影響です。

ビルドの評価フェーズ中:

  • プロパティは、表示される順序で定義および変更されます。プロパティ関数が実行されます。$(PropertyName) の形式のプロパティ値は、式内で展開されます。プロパティ値は展開された式に設定されます。
  • 項目定義は、表示される順序で定義および変更されます。プロパティ関数は、式内で既に展開されています。メタデータ値は、展開された式に設定されます。
  • 項目タイプは、表示される順序で定義および変更されます。@(ItemType) 形式のアイテム値が展開されます。アイテム変身も拡張。プロパティ関数と値は、式内で既に展開されています。アイテム リストとメタデータの値は、展開された式に設定されます。

ビルドの実行フェーズ中:

  • ターゲット内で定義されているプロパティと項目は 、出現順にまとめて評価されます。プロパティ関数が実行され、プロパティ値が式内で展開されます。アイテムの値とアイテムの変換も拡張されます。プロパティ値、アイテム タイプ値、およびメタデータ値は、展開された式に設定されます。」

そのリンクには別の重要なポイントがあります「(...)文字列の展開はビルドフェーズに依存しています。」.

プロパティ「Cfgs」を使用して、プロジェクトのフォルダーを再帰的にマップし、ワイルドカードを構成ファイルに定義しています(*.config)。ターゲット内で「Cfgs」を定義すると、InputConfigs は展開された Cfgs の値 (セミコロンで区切られたフォルダーの文字列リスト) を受け取り、ワイルドカードを解決するだけです。一方、ターゲットの外側で「Cfgs」を定義すると、@(ApplicationToDeploy->'%(RootDir)%(Directory)*.cs')InputConfigs は展開されていない Cfgs ( の値を受け取ります。InputConfigs がそれを展開すると、セミコロンで区切られたフォルダーの文字列リストになりますが、ワイルドカード(*.config).

Target ブロックの外で同じ結果を得ることができますか?

InputConfigs は常にディレクトリの展開されたリストを受け取るべきだと思います。拡張は、ビルドの実行段階で行われます。このフェーズでは、ターゲット内で定義されたプロパティとアイテムのみが評価されます。したがって、すべての初期化を「初期化」ターゲット ブロック内に保持します。Target ブロックの外でそれを行うことが不可能だと言っているわけではありませんが、前述の理由から、論理的ではないようです。=]

お役に立てれば、

于 2013-01-15T13:48:50.580 に答える