MSBuild:在另一个 CodeTaskFactory 目标中重用方法

MSBuild: re-use method from one CodeTaskFactory target in another one

由于描述不完善已更新。

我已经为“BeforeBuild”目标创建了这个 CodeTaskFactory MSBuild 任务:

<UsingTask
  TaskName="WriteIntoFileIfDifferent"
  TaskFactory="CodeTaskFactory"
  AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
  <ParameterGroup>
    <FileName ParameterType="System.String" Required="True" Output="False"/>
    <Text     ParameterType="System.String" Required="True" Output="False"/>
  </ParameterGroup>
  <Task>
    <Code Type="Class" Language="cs">
      <![CDATA[
        ...

        public class WriteIntoFileIfDifferent : Task
        {
          ...

          public override bool Execute ()
          {
            ...
            CopyFileIfNeeded (tempFileName, m_fileName);
            ...
          }

          private void CopyFileIfNeeded (string i_sourceFileName,
                                         string i_targetFileName)
          {
            ...
            CheckFileCopyNeeded (i_sourceFileName, i_targetFileName))
            ...
          }
          
          private static bool CheckFileCopyNeeded (string i_sourceFileName,
                                                  string i_targetFileName)
          {
            ...
            return !CheckStreamContentsEqual (sourceFileStream, targetFileStream);
            ...
          }

          private static bool CheckStreamContentsEqual (FileStream i_sourceFileStream,
                                                        FileStream i_targetFileStream)
          {
            ...
          }
        }
      ]]>
    </Code>
  </Task>
</UsingTask>

现在我已经创建了另一个相同类型的任务,也是为“BeforeBuild”目标创建的,它现在正在调用这两个任务。这两个任务都包含一个“CopyFileIfNeeded()”方法;它实际上是一个普通副本。

如何从两个任务中提取方法 CopyFileIfNeeded() 并将其放在一个单独的地方,以便两个任务都可以使用它?
这可能吗?
如果是,我如何在我的任务中调用这个方法?

如果有人对完整代码感兴趣,我可以在这里添加。

不确定如何使用 CodeTaskFactory 跨任务重新执行代码;这可能取决于如何准确地实施这些。例如。如果他们根据提供的代码创建一个 dll,您可以找出可以引用哪个 dll 并使用它的功能。但是,与其弄清楚是否是这种情况,我们也可以自己编写确切的原理:

  • 使用通用代码创建一个文件,Common.cs:

    namespace Foo
    {
      public static class Bar
      {
        public static bool CopyFileIfDifferent(string A, string B)
        {
          return true;
        }
      }
    }
    
  • 如果需要,即时构建该文件(应该仅在源文件更改或 dll 由于使用输入和输出而不存在时构建):

    <PropertyGroup>
      <CommonDll>$(Temp)\Common.dll</CommonDll>
    </PropertyGroup>
    
    <Target Name="BuildCommonDll" Inputs="$(MSBuildThisFileDirectory)Common.cs" Outputs="$(CommonDll)">
      <Csc Sources="$(MSBuildThisFileDirectory)Common.cs"
           References="System.dll;mscorlib.dll"
           TargetType="Library" OutputAssembly="$(CommonDll)"/>
    </Target>
    
  • 在您的任务中引用内置的 dll:

    <UsingTask
      TaskName="WriteIntoFileIfDifferent"
      TaskFactory="CodeTaskFactory"
      AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
      <ParameterGroup>
        <FileName ParameterType="System.String" Required="True" Output="False"/>
        <Text     ParameterType="System.String" Required="True" Output="False"/>
      </ParameterGroup>
      <Task>
        <Reference Include="$(CommonDll)" />
        <Code Type="Class" Language="cs">
          <![CDATA[
            using Foo;
    
            public class WriteIntoFileIfDifferent : Microsoft.Build.Utilities.Task
            {
              public string FileName{ get; set;}
    
              public string Text{ get; set;}
    
              public override bool Execute ()
              {
                var result = Foo.Bar.CopyFileIfDifferent(FileName, Text);
                Log.LogMessage("result = " + result.ToString());
                return true;
              }
            }
          ]]>
        </Code>
      </Task>
    </UsingTask>
    
  • 在调用它的目标中确保 dll 构建是一个依赖项:

    <Target Name="Build" DependsOnTargets="BuildCommonDll">
      <WriteIntoFileIfDifferent FileName="A" Text="B"/>
    </Target>
    

第一个 运行 的输出:

Project "c:\temp\foo.targets" on node 1 (Build target(s)).
BuildCommonDll:
  C:\Program Files (x86)\Microsoft Visual Studio17\Community\MSBuild.0\bin\Roslyn\csc.exe /reference:System
  .dll /reference:mscorlib.dll /out:c:\temp\Common.dll /target:library c:\temp\Common.cs
Build:
  result = True
Done Building Project "c:\temp\foo.targets" (Build target(s)).

连续运行s的输出:

Project "c:\temp\foo.targets" on node 1 (Build target(s)).
BuildCommonDll:
Skipping target "BuildCommonDll" because all output files are up-to-date with respect to the input files.
Build:
  result = True
Done Building Project "c:\temp\foo.targets" (Build target(s)).