如何从msbuild调用类静态方法并将其结果存储在列表中?
编辑:好的,让我再解释一下。我正在使用sandcastle帮助文件构建器为我的应用程序生成文档。其中一个要求是您必须按如下方式指定文档源:<DocumentationSources>
<DocumentationSource sourceFile="$(MSBuildProjectDirectory)\..\src\myApp\bin\Debug\myApp.exe" xmlns="" />
<DocumentationSource sourceFile="$(MSBuildProjectDirectory)\..\src\myApp\bin\Debug\myApp.xml" xmlns="" />
</DocumentationSources>
Sandcastle帮助文件构建器附带一个utils程序集,它可以从指定目录中检索所有dll和xml文件。我想从这个程序集中调用该方法,并将其结果存储为<DocumentationSource>
的列表。这是一个返回Collection<string>
答案 0 :(得分:17)
如果你想做一些简单的事情,自定义任务很棒,但潜在的过度杀伤力。我相信Draco正在询问Property Functions feature in MSBuild 4。
使用静态函数设置属性的示例(直接从上页翻录):
<Today>$([System.DateTime]::Now)</Today>
并在参数上调用静态函数:
$([Class]:: Property.Method(Parameters))
或者,也许你想要像inline tasks这样疯狂的东西。
答案 1 :(得分:3)
创建一个自定义任务,调用该静态方法并返回一个ITaskItem数组。
或者
您可以尝试使用MSBuild Extension Pack Assembly.Invoke :
<PropertyGroup>
<StaticMethodAssemblyPath>path</StaticMethodAssemblyPath>
</PropertyGroup>
<MSBuild.ExtensionPack.Framework.Assembly TaskAction="Invoke"
NetArguments="@(ArgsM)"
NetClass="StaticMethodClassName"
NetMethod="StaticMethodName"
NetAssembly="${StaticMethodAssemblyPath}">
<Output TaskParameter="Result" PropertyName="R"/>
</MSBuild.ExtensionPack.Framework.Assembly>
答案 2 :(得分:2)
通常,最灵活的选择是创建custom MSBuild task。这是所有未经测试的代码,只是为了给你一个想法:
在你的msbuild文件中:
<UsingTask TaskName="FindFiles" AssemblyFile="FindFiles.dll" />
<!--
As you'll see below, SearchDirectory and SearchPatterns are input parameters,
MatchingFiles is an output parameter, SourceFiles is an ItemGroup assigned to
the output.
-->
<FindFiles SearchDirectory="$(MyDirectory)" SearchPatterns="*.dll;*.xml">
<Output ItemName="SourceFiles" TaskParameter="MatchingFiles" />
</FindFiles>
<!-- You can then use the generated ItemGroup output elsewhere. -->
<DocumentationSources>
<DocumentationSource sourceFile="@(SourceFiles)" xmlns="" />
</DocumentationSources>
FindFiles.cs:
using System;
using System.IO;
using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace FindFiles
{
public class FindFiles : Task
{
// input parameter
[Required]
public string SearchDirectory { get; set; }
// output parameter
[Required]
public string[] SearchPatterns { get; set; }
[Output]
public string[] MatchingFiles { get; private set; }
private bool ValidateParameters()
{
if (String.IsNullOrEmpty(SearchDirectory))
{
return false;
}
if (!Directory.Exists(SearchDirectory))
{
return false;
}
if (SearchPatterns == null || SearchPatterns.Length == 0)
{
return false;
}
return true;
}
// MSBuild tasks use the command pattern, this is where the magic happens,
// refactor as needed
public override bool Execute()
{
if (!ValidateParameters())
{
return false;
}
List<string> matchingFiles = new List<string>();
try
{
foreach (string searchPattern in SearchPatterns)
{
matchingFiles.AddRange(
Directory.GetFiles(SearchDirectory, searchPattern)
);
}
}
catch (IOException)
{
// it might be smarter to just let this exception fly, depending on
// how you want the task to behave
return false;
}
MatchingFiles = matchingFiles.ToArray();
return true;
}
}
}