Nota
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare ad accedere o a cambiare directory.
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare a cambiare directory.
Le attività MSBuild vengono in genere create compilando una classe che implementa l'interfaccia ITask . Per altre informazioni, vedere Tasks.
Quando si desidera evitare il sovraccarico della creazione di un'attività compilata, è possibile creare un'attività inline nel file di progetto o in un file importato. Non è necessario creare un assembly separato per ospitare l'attività. L'uso di un'attività inline rende più semplice tenere traccia del codice sorgente e semplificare la distribuzione dell'attività. Il codice sorgente è integrato nel file di progetto MSBuild o nel file importato, in genere un .targets file.
Si crea un'attività inline usando una factory di attività di codice. Per lo sviluppo corrente, assicurarsi di usare RoslynCodeTaskFactory, non CodeTaskFactory.
CodeTaskFactory supporta solo le versioni C# fino alla 4.0.
Le attività inline sono pensate per offrire praticità per compiti piccoli che non richiedono dipendenze complesse. Il supporto del debug per le attività inline è limitato. È consigliabile creare un'attività compilata anziché un'attività inline quando si vuole scrivere codice più complesso, fare riferimento a un pacchetto NuGet, eseguire strumenti esterni o eseguire operazioni che potrebbero produrre condizioni di errore. Inoltre, le attività inline vengono compilate ogni volta che si compila, in modo da avere un impatto notevole sulle prestazioni di compilazione.
Struttura di un'attività in linea
Un'attività inline è contenuta in un elemento UsingTask . L'attività inline e l'elemento UsingTask che lo contiene vengono in genere inclusi in un .targets file e importati in altri file di progetto in base alle esigenze. Ecco un'attività inline di base che non esegue alcuna operazione, ma illustra la sintassi:
<!-- This simple inline task does nothing. -->
<UsingTask
TaskName="DoNothing"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Reference Include="" />
<Using Namespace="" />
<Code Type="Fragment" Language="cs">
</Code>
</Task>
</UsingTask>
L'elemento UsingTask nell'esempio ha tre attributi che descrivono l'attività e la factory di attività inline che la compila.
L'attributo
TaskNameassegna un nome all'attività, in questo caso .DoNothingL'attributo
TaskFactoryassegna un nome alla classe che implementa la task factory inline.L'attributo
AssemblyFilefornisce la posizione della factory di attività inline. In alternativa, è possibile utilizzare l'attributoAssemblyNameper specificare il nome completo della classe task factory inline, che si trova in genere in$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll.
Gli elementi rimanenti dell'attività DoNothing sono vuoti e vengono forniti per illustrare l'ordine e la struttura di un'attività inline. Un esempio completo viene presentato più avanti in questo articolo.
L'elemento
ParameterGroupè facoltativo. Se specificato, dichiara i parametri per l'attività. Per altre informazioni sui parametri di input e output, vedere Parametri di input e output più avanti in questo articolo.L'elemento
Taskdescrive e contiene il codice sorgente dell'attività.L'elemento
Referencespecifica i riferimenti agli assembly .NET usati nel codice. L'uso di questo elemento equivale all'aggiunta di un riferimento a un progetto in Visual Studio. L'attributoIncludespecifica il percorso dell'assembly a cui si fa riferimento. Gli assembly in mscorlib, .NET Standard, Microsoft.Build.Framework e Microsoft.Build.Utilities.Core, nonché alcuni assembly a cui viene fatto riferimento transitivamente come dipendenze, sono disponibili senza .ReferenceL'elemento
Usingelenca gli spazi dei nomi a cui si vuole accedere. Questo elemento equivale allausingdirettiva in C#. L'attributoNamespacespecifica lo spazio dei nomi da includere. Non è possibile inserire una direttivausingnel codice inline, perché tale codice viene inserito in un corpo del metodo, dove le direttiveusingnon sono consentite.
Reference e Using gli elementi sono indipendenti dalla lingua. Le attività inline possono essere scritte in Visual Basic o C#.
Annotazioni
Gli elementi contenuti nell'elemento Task sono specifici della factory delle attività, in questo caso la factory dell'attività di codice.
Elemento di codice
L'ultimo elemento figlio da visualizzare all'interno dell'elemento Task è l'elemento Code. L'elemento Code contiene o individua il codice che si desidera compilare in un'attività. Ciò che si inserisce nell'elemento Code dipende dalla modalità di scrittura dell'attività.
L'attributo Language specifica il linguaggio in cui viene scritto il codice. I valori accettabili sono cs per C#, vb per Visual Basic.
L'attributo Type specifica il tipo di codice trovato nell'elemento Code .
Se il valore di
TypeèClass, l'elementoCodecontiene il codice per una classe che deriva dall'interfaccia ITask .Se il valore di
TypeèMethod, il codice definisce una sovrascrittura del metodoExecutedell'interfaccia ITask.Se il valore di
TypeèFragment, il codice definisce il contenuto delExecutemetodo, ma non la firma o l'istruzionereturn.
Il codice stesso viene in genere visualizzato tra un <![CDATA[ marcatore e un ]]> marcatore. Poiché il codice si trova in una sezione CDATA, non è necessario preoccuparsi dell'escape dei caratteri riservati, ad esempio "<" o ">".
In alternativa, è possibile usare l'attributo Source dell'elemento Code per specificare il percorso di un file che contiene il codice per l'attività. Il codice nel file di origine deve essere del tipo specificato dall'attributo Type . Se l'attributo Source è presente, il valore predefinito di Type è Class. Se Source non è presente, il valore predefinito è Fragment.
Annotazioni
Quando si definisce la classe task nel file di origine, il nome della classe deve accettare l'attributo dell'elemento TaskNameUsingTask corrispondente.
HelloWorld
Ecco un esempio di una semplice attività inlinea. L'attività HelloWorld visualizza "Hello, world!" nel dispositivo di registrazione degli errori predefinito, che in genere è la console di sistema o la finestra Output di Visual Studio.
<Project>
<!-- This simple inline task displays "Hello, world!" -->
<UsingTask
TaskName="HelloWorld"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Using Namespace="System"/>
<Using Namespace="System.IO"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
// Display "Hello, world!"
Log.LogError("Hello, world!");
]]>
</Code>
</Task>
</UsingTask>
</Project>
È possibile salvare l'attività HelloWorld in un file denominato HelloWorld.targets e richiamarlo da un progetto come indicato di seguito.
<Project>
<Import Project="HelloWorld.targets" />
<Target Name="Hello">
<HelloWorld />
</Target>
</Project>
Parametri di input e output
I parametri dell'attività inline sono elementi figlio dell'elemento ParameterGroup. Ogni parametro accetta il nome dell'elemento che lo definisce. Il codice seguente definisce il parametro Text.
<ParameterGroup>
<Text />
</ParameterGroup>
I parametri possono avere uno o più di questi attributi:
-
Requiredè un attributo facoltativo che èfalseper impostazione predefinita. Setrue, il parametro è obbligatorio e deve essere assegnato un valore prima di chiamare l'attività. -
ParameterTypeè un attributo facoltativo che èSystem.Stringper impostazione predefinita. Può essere impostato su qualsiasi tipo completo che sia un elemento o un valore che può essere convertito in e da una stringa usando ChangeType. In altre parole, qualsiasi tipo che può essere passato a e da un'attività esterna. -
Outputè un attributo facoltativo che èfalseper impostazione predefinita. Setrue, al parametro deve essere assegnato un valore prima di restituire dal metodo Execute.
Ad esempio:
<ParameterGroup>
<Expression Required="true" />
<Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<Tally ParameterType="System.Int32" Output="true" />
</ParameterGroup>
definisce questi tre parametri:
Expressionè un parametro di input obbligatorio di tipo System.String.Filesè un parametro di input dell'elenco di elementi obbligatorio.Tallyè un parametro di output di tipo System.Int32.
Se l'elemento ha l'attributo CodeType di Fragment o Method, le proprietà vengono create automaticamente per ogni parametro. In caso contrario, le proprietà devono essere dichiarate in modo esplicito nel codice sorgente dell'attività e devono corrispondere esattamente alle definizioni dei parametri.
Eseguire il debug di un'attività inline
MSBuild genera un file sorgente per l'attività inline e scrive l'output in un file di testo con un nome GUID nella cartella dei file temporanei AppData\Local\Temp\MSBuildTemp. L'output viene in genere eliminato, ma per mantenere questo file di output, è possibile impostare la variabile MSBUILDLOGCODETASKFACTORYOUTPUT di ambiente su 1.
Esempio 1
L'attività inline seguente sostituisce ogni occorrenza di un token nel file specificato con il valore specificato.
<Project>
<UsingTask TaskName="TokenReplace" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<Path ParameterType="System.String" Required="true" />
<Token ParameterType="System.String" Required="true" />
<Replacement ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs"><![CDATA[
string content = File.ReadAllText(Path);
content = content.Replace(Token, Replacement);
File.WriteAllText(Path, content);
]]></Code>
</Task>
</UsingTask>
<Target Name='Demo' >
<TokenReplace Path="Target.config" Token="$MyToken$" Replacement="MyValue"/>
</Target>
</Project>
Esempio 2
L'attività inline seguente genera l'output serializzato. In questo esempio viene illustrato l'uso di un parametro di output e di un riferimento.
<Project>
<PropertyGroup>
<RoslynCodeTaskFactoryAssembly Condition="$(RoslynCodeTaskFactoryAssembly) == ''">$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll</RoslynCodeTaskFactoryAssembly>
</PropertyGroup>
<UsingTask
TaskName="MyInlineTask"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(RoslynCodeTaskFactoryAssembly)">
<ParameterGroup>
<Input ParameterType="System.String" Required="true" />
<Output ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Text.Json" /> <!-- Reference an assembly -->
<Using Namespace="System.Text.Json" /> <!-- Use a namespace -->
<Code Type="Fragment" Language="cs">
<![CDATA[
Output = JsonSerializer.Serialize(new { Message = Input });
]]>
</Code>
</Task>
</UsingTask>
<Target Name="RunInlineTask">
<MyInlineTask Input="Hello, Roslyn!" >
<Output TaskParameter="Output" PropertyName="SerializedOutput" />
</MyInlineTask>
<Message Text="Serialized Output: $(SerializedOutput)" />
</Target>
</Project>