Ответ 1
Наконец-то мне удалось автоматически выполнить копирование из Project B без необходимости его изменения. IIya не был так далек от решения, но факт заключается в том, что я не могу создать статически, поскольку список файлов, создаваемых из Project A с MyCustomTask, является динамическим. После копания большего количества в Microsoft.Common.targets
, я обнаружил, что ProjectB получит список результатов из Project A, вызвав целевой GetCopyToOutputDirectoryItems
. Эта цель зависит от AssignTargetPaths
, которая сама зависит от свойства списка целей AssignTargetPathsDependsOn
.
Итак, чтобы генерировать динамическое содержимое и автоматически копировать этот контент с помощью стандартной зависимости проекта, нам нужно подключить Project A в двух разных местах:
- В
AssignTargetPathsDependsOn
, поскольку он косвенно обозначается Project B в проекте A через GetCopyToOutputDirectoryItems. А также он косвенно называется Проектом А при вызовеPrepareResource
. Здесь мы просто выводим список файлов, которые будут сгенерированы (по проекту 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>
Этот метод работает с anykind проектов С#, использующих Common.Targets(поэтому он работает с чистым рабочим столом, WinRT XAML App или Windows Phone 8).