Updated due to weak description.
I have created this CodeTaskFactory MSBuild Task for the "BeforeBuild" Target:
<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>
Now I have created another Task of the same type, also for the "BeforeBuild" Target, which is now calling both tasks. Both tasks contain a "CopyFileIfNeeded()" method; it's actually a plain copy.
How can I extract the method CopyFileIfNeeded()
from both tasks and put it at a separate place, so that both tasks can use it?
Is this even possible?
If yes, how can I call this method in my tasks?
If someone is interested in the full code, I can add it here.
Not sure how to resue code across Tasks using CodeTaskFactory; it might be possible depedning on how those are implemented exactly. E.g. if they'd create a dll from the code supplied and you can figure out which dll you could reference it and use it's functions. But instead of figuring out whether that is the case, we can also just write that exact principle ourselves:
create a file with the common code, Common.cs
:
namespace Foo
{
public static class Bar
{
public static bool CopyFileIfDifferent(string A, string B)
{
return true;
}
}
}
build that file on the fly if needed (should only build if the source file changes or the dll does not exist because of using Inputs and Outputs):
<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>
in your Task(s) reference the built 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>
in the Targets invoking this make sure the dll building is a dependency:
<Target Name="Build" DependsOnTargets="BuildCommonDll">
<WriteIntoFileIfDifferent FileName="A" Text="B"/>
</Target>
Output of first run:
Project "c:\temp\foo.targets" on node 1 (Build target(s)).
BuildCommonDll:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.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)).
Output of consecutive runs:
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)).