2017-12-24 34 views
2

MSBuild 작업간에 Dictionary 또는 Hashtable을 보내거나 공유하려고합니다.MSBuild 작업의 Hashtable/Dictionary 매개 변수

다음 두 가지 사용자 지정 작업, 즉 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

I가 속성에 해시 테이블 또는 사전을 사용할 수있는 방법을 사용자 지정 MSBuild 작업?

답변

3

작업을 수행 할 수있는 매개 변수는 ITaskItem 또는 ITaskItem의 배열로 제한됩니다.

그래서 당신의 재산은 요구 사항에 맞게

public ITaskItem[] Output { get; set; } 

public Hashtable Output { get; set; } 

에서 변경해야합니다.

다음으로 ITaskItem을 구현하는 구현 클래스가 필요합니다. 이를 통해 해시 셋이나 사전을 처리 할 수 ​​있습니다. 난 당신이 추가하지만 대한 최소한의 키 값 클래스는 다음과 같이 수 있다고 왼쪽 :

이 클래스는 생산이면은 MSBuild 스크립트에서 수행 한 경우이 보이는 모양 항목 것
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; 
    } 
} 

:

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

다음이 새로운 클래스 키 값을 사용하여 작업 설정을 적용하고 얻을 수 있습니다 :

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)