2016-05-12 6 views
1

Es ist mir nicht klar, was der Zweck der WriteCodeFragment Aufgabe ist (https://msdn.microsoft.com/en-us/library/microsoft.build.tasks.writecodefragment.aspx). Google scheint die Dokumentation auf den Kopf zu stellen und das Beispiel, das ich gesehen habe, ist nicht definitiv.MSBuild WriteCodeFragment Aufgabe

Kann jemand klären? Vielen Dank.

+0

gefunden eine Referenz hier https://github.com/Microsoft/msbuild/blob/c1459f5cbd36f2c33eafc8f4ff087f6ee84c3640/src/XMakeTasks/Microsoft.Common.CurrentVersion.targets#L3030, keine Ahnung, was es genau macht – stijn

+1

@stijn Siehe die Antwort, nachdem ich ein wenig mehr untersucht habe. –

Antwort

2

Es sieht aus wie es nur gut ist, eine Sourcecode-Datei zum Bestücken (Ihre Wahl der Sprache) mit Attributen (sprich: der Einbettung von Informationen in ein Projekt erstellen).

Dies ist der Quellcode für die Aufgabe:

https://github.com/Microsoft/msbuild/blob/master/src/XMakeTasks/WriteCodeFragment.cs

Die spezifischen Gene() Methode Referenz. Der Typ, der es in erster Linie Aussehen Aufzählen Attribut spezifisch sein (sprich: deklarative und nicht-funktionalen):

/// <summary> 
/// Generates the code into a string. 
/// If it fails, logs an error and returns null. 
/// If no meaningful code is generated, returns empty string. 
/// Returns the default language extension as an out parameter. 
/// </summary> 
[SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor(System.Text.StringBuilder)", Justification = "Reads fine to me")] 
private string GenerateCode(out string extension) 
{ 
    extension = null; 
    bool haveGeneratedContent = false; 

    CodeDomProvider provider; 

    try 
    { 
     provider = CodeDomProvider.CreateProvider(Language); 
    } 
    catch (ConfigurationException ex) 
    { 
     Log.LogErrorWithCodeFromResources("WriteCodeFragment.CouldNotCreateProvider", Language, ex.Message); 
     return null; 
    } 
    catch (SecurityException ex) 
    { 
     Log.LogErrorWithCodeFromResources("WriteCodeFragment.CouldNotCreateProvider", Language, ex.Message); 
     return null; 
    } 

    extension = provider.FileExtension; 

    CodeCompileUnit unit = new CodeCompileUnit(); 

    CodeNamespace globalNamespace = new CodeNamespace(); 
    unit.Namespaces.Add(globalNamespace); 

    // Declare authorship. Unfortunately CodeDOM puts this comment after the attributes. 
    string comment = ResourceUtilities.FormatResourceString("WriteCodeFragment.Comment"); 
    globalNamespace.Comments.Add(new CodeCommentStatement(comment)); 

    if (AssemblyAttributes == null) 
    { 
     return String.Empty; 
    } 

    // For convenience, bring in the namespaces, where many assembly attributes lie 
    globalNamespace.Imports.Add(new CodeNamespaceImport("System")); 
    globalNamespace.Imports.Add(new CodeNamespaceImport("System.Reflection")); 

    foreach (ITaskItem attributeItem in AssemblyAttributes) 
    { 
     CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(new CodeTypeReference(attributeItem.ItemSpec)); 

     // Some attributes only allow positional constructor arguments, or the user may just prefer them. 
     // To set those, use metadata names like "_Parameter1", "_Parameter2" etc. 
     // If a parameter index is skipped, it's an error. 
     IDictionary customMetadata = attributeItem.CloneCustomMetadata(); 

     List<CodeAttributeArgument> orderedParameters = new List<CodeAttributeArgument>(new CodeAttributeArgument[customMetadata.Count + 1] /* max possible slots needed */); 
     List<CodeAttributeArgument> namedParameters = new List<CodeAttributeArgument>(); 

     foreach (DictionaryEntry entry in customMetadata) 
     { 
      string name = (string)entry.Key; 
      string value = (string)entry.Value; 

      if (name.StartsWith("_Parameter", StringComparison.OrdinalIgnoreCase)) 
      { 
       int index; 

       if (!Int32.TryParse(name.Substring("_Parameter".Length), out index)) 
       { 
        Log.LogErrorWithCodeFromResources("General.InvalidValue", name, "WriteCodeFragment"); 
        return null; 
       } 

       if (index > orderedParameters.Count || index < 1) 
       { 
        Log.LogErrorWithCodeFromResources("WriteCodeFragment.SkippedNumberedParameter", index); 
        return null; 
       } 

       // "_Parameter01" and "_Parameter1" would overwrite each other 
       orderedParameters[index - 1] = new CodeAttributeArgument(String.Empty, new CodePrimitiveExpression(value)); 
      } 
      else 
      { 
       namedParameters.Add(new CodeAttributeArgument(name, new CodePrimitiveExpression(value))); 
      } 
     } 

     bool encounteredNull = false; 
     for (int i = 0; i < orderedParameters.Count; i++) 
     { 
      if (orderedParameters[i] == null) 
      { 
       // All subsequent args should be null, else a slot was missed 
       encounteredNull = true; 
       continue; 
      } 

      if (encounteredNull) 
      { 
       Log.LogErrorWithCodeFromResources("WriteCodeFragment.SkippedNumberedParameter", i + 1 /* back to 1 based */); 
       return null; 
      } 

      attribute.Arguments.Add(orderedParameters[i]); 
     } 

     foreach (CodeAttributeArgument namedParameter in namedParameters) 
     { 
      attribute.Arguments.Add(namedParameter); 
     } 

     unit.AssemblyCustomAttributes.Add(attribute); 
     haveGeneratedContent = true; 
    } 

    StringBuilder generatedCode = new StringBuilder(); 

    using (StringWriter writer = new StringWriter(generatedCode, CultureInfo.CurrentCulture)) 
    { 
     provider.GenerateCodeFromCompileUnit(unit, writer, new CodeGeneratorOptions()); 
    } 

    string code = generatedCode.ToString(); 

    // If we just generated infrastructure, don't bother returning anything 
    // as there's no point writing the file 
    return haveGeneratedContent ? code : String.Empty; 
} 

, dass nur ein weiteres Beispiel, das ich gefunden war:

(Using WriteCodeFragment MSBuild Task)

<Target Name="BeforeBuild"> 
    <ItemGroup> 
    <AssemblyAttributes Include="AssemblyVersion"> 
     <_Parameter1>123.132.123.123</_Parameter1> 
    </AssemblyAttributes> 
    </ItemGroup> 
    <WriteCodeFragment Language="C#" OutputFile="BuildVersion.cs" AssemblyAttributes="@(AssemblyAttributes)" /> 
</Target> 

diese in einen tatsächlichen Build Anstecken macht:

//------------------------------------------------------------------------------ 
// <auto-generated> 
//  This code was generated by a tool. 
//  Runtime Version:4.0.30319.42000 
// 
//  Changes to this file may cause incorrect behavior and will be lost if 
//  the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

using System; 
using System.Reflection; 

[assembly: AssemblyVersion("123.132.123.123")] 

// Generated by the MSBuild WriteCodeFragment class. 
+0

Ich wäre daran interessiert herauszufinden, wie man es daran hindern kann, diese Aufgabe zu erledigen. –

Verwandte Themen