2017-12-24 22 views
2

MSBuildタスクの間にDictionaryまたはHashtableを送信/共有しようとしています。MSBuildタスクのHashtable/Dictionaryパラメータ

次の2つのカスタムタスク、つまりHashtableを生成するGetと、それを消費するSetがあります。

Get.cs

public class Get : Task 
{ 
    [Output] 
    public Hashtable Output { get; set; } 

    public override bool Execute() 
    { 
     Output = new Hashtable(); 
     return true; 
    } 
} 

Set.cs

public class Set : Task 
{ 
    [Required] 
    public Hashtable Output { get; set; } 

    public override bool Execute() 
    { 
     var items = Output.Cast<DictionaryEntry>().ToDictionary(d => d.Key.ToString(), d => d.Value.ToString()); 

     foreach(var item in items) 
     { 
      //Do Something 
     } 

     return true; 
    } 
} 

上記のクラスは、私は、次のビルドターゲットスクリプトでAssembly.dllことを使用Assembly.dll

に罰金構築カスタムタスクの取得と設定を呼び出す:

MyTarget.targets

<?xml version="1.0" encoding="utf-8"?> 
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <UsingTask TaskName="Get" AssemblyFile=".\Assembly.dll"/> 
    <UsingTask TaskName="Set" AssemblyFile=".\Assembly.dll"/> 

    <Target Name="Get"> 

    <Get> 
     <Output TaskParameter="Output" ItemName="Output" /> 
    </Get> 
    <Set [email protected](Output) /> 

    </Target> 

</Project> 

私は上記のターゲットでプロジェクトをビルドするMSBuildのは、次のエラーを示しています。私はのためのプロパティでハッシュテーブルや辞書を使用するにはどうすればよい

The "System.Collections.Hashtable" type of the "Output" parameter of the "Get" task is not supported by MSBuild

カスタムMSBuildタスク?

答えて

3

タスクに出入りできるパラメータは、ITaskItemまたはITaskItemの配列に制限されています。

だからあなたの性質は、その要件に合うように

public ITaskItem[] Output { get; set; } 

public Hashtable Output { get; set; } 

から変更する必要があります。

次に、ITaskItemを実装する実装クラスが必要です。それはあなたのハッシュセットや辞書を処理することができます。

public class KeyValue: ITaskItem 
{ 
    string _spec = String.Empty; 

    public KeyValue(string key, string value) 
    { 
     _spec = key; 
     metadata.Add("value", value); 
    } 

    Dictionary<string,string> metadata = new Dictionary<string,string>(); 

    public string ItemSpec 
    { 
     get {return _spec;} 
     set {} 
    } 
    public ICollection MetadataNames 
    { 
     get {return metadata.Keys;} 
    } 
    public int MetadataCount 
    { 
     get {return metadata.Keys.Count;} 
    } 
    public string GetMetadata(string metadataName) 
    { 
     return metadata[metadataName]; 
    } 
    public void SetMetadata(string metadataName, string metadataValue) 
    { 
     metadata[metadataName] = metadataValue; 
    } 
    public void RemoveMetadata(string metadataName) 
    { 
    } 
    public void CopyMetadataTo(ITaskItem destinationItem) 
    { 
    } 
    public IDictionary CloneCustomMetadata() 
    { 
      return metadata; 
    } 
} 

このクラスは、生産し、それが平面のMSBuildスクリプトで行われた場合は、これを見て見ていきます項目ます:私は追加しますが、最小限のです。KeyValueクラスは次のようになりますあなたのためにそれを残し

<Item Include="key"> 
    <value>some value</value> 
</Item> 

次は、この新しいクラスです。KeyValueを使用するようにタスクを設定を適応して入手することができます

public class Set : Task 
{ 

    TaskLoggingHelper log; 

    public Set() { 
     log = new TaskLoggingHelper(this); 
    } 

    [Required] 
    public ITaskItem[] Output { get; set; } 

    public override bool Execute() 
    { 
     log.LogMessage("start set"); 
     foreach(var item in Output) 
     { 
      log.LogMessage(String.Format("Set sees key {0} with value {1}.",item.ItemSpec, item.GetMetadata("value"))); 
     } 
     log.LogMessage("end set"); 
     return true; 
    } 
} 

public class Get : Task 
{ 

    // notice this property no longer is called Output 
    // as that gave me errors as the property is reserved  
    [Output] 
    public ITaskItem[] Result { get; set; } 

    public override bool Execute() 
    { 
     // convert a Dictionary or Hashset to an array of ITaskItems 
     // by creating instances of the class KeyValue. 
     // I use a simple list here, I leave it as an exercise to do the other colletions 
     Result = new List<ITaskItem> { new KeyValue("bar", "bar-val"), new KeyValue("foo","foo val") }.ToArray(); 
     return true; 
    } 
} 

私は上記のコードをテストするために使用するビルドファイル:

実行すると
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <UsingTask TaskName="Get" AssemblyFile=".\cb.dll"/> 
    <UsingTask TaskName="Set" AssemblyFile=".\cb.dll"/> 

    <Target Name="Get"> 

    <Get> 
     <Output TaskParameter="Result" ItemName="GetResult" /> 
    </Get> 

    <!-- lets see what we've got --> 
    <Message Importance="high" Text="key: @(GetResult) :: value: %(value)" /> 

    <Set Output="@(GetResult)"> 

    </Set> 

    </Target> 

</Project> 

結果は以下のようになります。

Build started 24-12-2017 21:26:17. 
Project "C:\Prj\bld\test.build" on node 1 (default targets). 
Get: 
    key: bar :: value: bar-val 
    key: foo :: value: foo val 
    start set 
    Set sees key bar with value bar-val. 
    Set sees key foo with value foo val. 
    end set 
Done Building Project "C:\Prj\bld\test.build" (default targets). 


Build succeeded. 
    0 Warning(s) 
    0 Error(s) 
関連する問題