我终于设法自动执行来自项目 B的副本,而无需修改它。IIya 离解决方案不远,但事实是我无法静态生成,因为使用 MyCustomTask从项目 A生成的文件列表是动态的。在深入挖掘之后Microsoft.Common.targets
,我发现 ProjectB 将通过调用 target来获取Project AGetCopyToOutputDirectoryItems
的输出列表。此目标依赖于其AssignTargetPaths
本身依赖于目标列表属性AssignTargetPathsDependsOn
。
因此,为了动态生成内容并通过标准项目依赖项自动复制此内容,我们需要在两个不同的地方挂钩项目 A :
AssignTargetPathsDependsOn
因为它是由项目 B通过 GetCopyToOutputDirectoryItems在项目 A上间接调用的。并且它在被调用时被项目 APrepareResource
间接调用。在这里,我们只是输出将生成(由Project A)或由Project B使用的文件列表。AssignTargetPathsDependsOn 将调用一个自定义任务MyCustomTaskList
,该任务只负责输出文件列表(但不生成它们),这个文件列表将创建动态“内容” CopyOutputDirectory
。
- 为了
BuildDependsOn
实际生成Project A中的内容。这将调用MyCustomTask
生成内容。
所有这些都是在 ProjectA 中这样设置的:
<!-- In Project A -->
<!-- Task to generate the files -->
<UsingTask TaskName="MyCustomTask" AssemblyFile="$(PathToMyCustomTaskAssembly)"/>
<!-- Task to output the list of generated of files - It doesn't generate the file -->
<UsingTask TaskName="MyCustomTaskList" AssemblyFile="$(PathToMyCustomTaskAssembly)"/>
<!-- 1st PART : When Project A is built, It will generate effectively the files -->
<PropertyGroup>
<BuildDependsOn>
MyCustomTaskTarget;
$(BuildDependsOn);
</BuildDependsOn>
</PropertyGroup>
<Target Name="MyCustomTaskTarget">
<!-- Call MyCustomTask generate the files files that will be generated by MyCustomTask -->
<MyCustomTask
ProjectDirectory="$(ProjectDir)"
IntermediateDirectory="$(IntermediateOutputPath)"
Files="@(MyCustomFiles)"
RootNamespace="$(RootNamespace)"
>
</MyCustomTask>
</Target>
<!-- 2nd PART : When Project B is built, It will call GetCopyToOutputDirectoryItems on ProjectA so we need to generate this list when it is called -->
<!-- For this we need to override AssignTargetPathsDependsOn in order to generate the list of files -->
<!-- as GetCopyToOutputDirectoryItems ultimately depends on AssignTargetPathsDependsOn -->
<!-- Content need to be generated before AssignTargets, because AssignTargets will prepare all files to be copied later by GetCopyToOutputDirectoryItems -->
<!-- This part is also called from ProjectA when target 'PrepareResources' is called -->
<PropertyGroup>
<AssignTargetPathsDependsOn>
$(AssignTargetPathsDependsOn);
MyCustomTaskListTarget;
</AssignTargetPathsDependsOn>
</PropertyGroup>
<Target Name="MyCustomTaskListTarget">
<!-- Call MyCustomTaskList generating the list of files that will be generated by MyCustomTask -->
<MyCustomTaskList
ProjectDirectory="$(ProjectDir)"
IntermediateDirectory="$(IntermediateOutputPath)"
Files="@(MyCustomFiles)"
RootNamespace="$(RootNamespace)"
>
<Output TaskParameter="ContentFiles" ItemName="MyCustomContent"/>
</MyCustomTaskList>
<ItemGroup>
<!--Generate the lsit of content generated by MyCustomTask -->
<Content Include="@(MyCustomContent)" KeepMetadata="Link;CopyToOutputDirectory"/>
</ItemGroup>
</Target>
此方法适用于使用 Common.Targets 的任何类型的 C# 项目(因此它适用于纯桌面、WinRT XAML 应用程序或 Windows Phone 8 项目)。