Attività inline di MSBuild
Le attività di MSBuild in genere vengono create compilando una classe che implementa l'interfaccia ITask. Per altre informazioni, vedere Tasks (Attività).
A partire dalla versione 4 di .NET Framework è possibile creare attività inline nel file di progetto. Non è necessario creare un assembly separato per ospitare l'attività. In questo modo è più semplice tenere traccia del codice sorgente e distribuire l'attività. Il codice sorgente è integrato nello script.
In MSBuild 15.8 è stato aggiunto RoslynCodeTaskFactory . Per lo sviluppo corrente, assicurarsi di usare RoslynCodeTaskFactory, non CodeTaskFactory. CodeTaskFactory supporta solo le versioni C# fino alla 4.0.
Struttura di un'attività inline
Un'attività inline è contenuta in un elemento UsingTask. L'attività inline e l'elemento UsingTask
che la contiene sono generalmente inclusi in un file con estensione targets e all'occorrenza vengono importati in altri file di progetto. Di seguito è riportata un'attività inline di base. Si noti che non esegue alcuna operazione.
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This simple inline task does nothing. -->
<UsingTask
TaskName="DoNothing"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Reference Include="" />
<Using Namespace="" />
<Code Type="Fragment" Language="cs">
</Code>
</Task>
</UsingTask>
</Project>
L'elemento UsingTask
nell'esempio ha tre attributi che descrivono l'attività e la factory dell'attività inline che la compila.
L'attributo
TaskName
assegna un nome all'attività, in questo casoDoNothing
.L'attributo
TaskFactory
assegna un nome alla classe che implementa la factory dell'attività inline.L'attributo
AssemblyFile
assegna la posizione della factory dell'attività inline. In alternativa, è possibile usare l'attributoAssemblyName
per specificare il nome completo della classe factory dell'attività inline, che si trova in genere in$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll
.
Gli elementi rimanenti dell'attività DoNothing
sono vuoti e vengono specificati per illustrare l'ordine e la struttura di un'attività inline. Un esempio più concreto è riportato più avanti in questo argomento.
L'elemento
ParameterGroup
è facoltativo. Se specificato, consente di dichiarare i parametri per l'attività. Per altre informazioni sui parametri di input e output, vedere Parametri di input e output più avanti in questo argomento.L'elemento
Task
descrive e contiene il codice sorgente dell'attività.L'elemento
Reference
specifica i riferimenti agli assembly .NET usati nel codice. Equivale all'aggiunta di un riferimento a un progetto in Visual Studio. L'attributoInclude
specifica il percorso dell'assembly di riferimento.L'elemento
Using
indica gli spazi dei nomi a cui si vuole accedere. Ricorda l'istruzioneUsing
in Visual C#. L'attributoNamespace
specifica lo spazio dei nomi da includere.
Gli elementi Reference
e Using
sono indipendenti dal linguaggio di programmazione. Le attività inline possono essere scritte in uno dei linguaggi .NET CodeDOM supportati, ad esempio Visual Basic, Visual C#.
Nota
Gli elementi contenuti in Task
sono specifici della factory dell'attività, in questo caso la factory dell'attività del codice.
Elemento coda
L'ultimo elemento figlio visualizzato all'interno dell'elemento Task
è l'elemento Code
. L'elemento Code
contiene o individua il codice che deve essere compilato in un'attività. Ciò che si inserisce nell'elemento Code
dipende da come si vuole scrivere l'attività.
L'attributo Language
specifica il linguaggio di programmazione in cui è scritto il codice. I valori accettabili sono cs
per C#, vb
per Visual Basic.
L'attributo Type
specifica il tipo di codice rilevato nell'elemento Code
.
Se il valore di
Type
èClass
, l'elementoCode
contiene il codice per una classe che deriva dall'interfaccia ITask.Se il valore di
Type
èMethod
, il codice definisce un override del metodoExecute
dell'interfaccia ITask.Se il valore di
Type
èFragment
, il codice definisce il contenuto del metodoExecute
ma non la firma o l'istruzionereturn
.
Il codice in genere è visualizzato tra un indicatore <![CDATA[
e un indicatore ]]>
. 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
.
Nota
Quando si definisce la classe dell'attività nel file di origine il nome della classe deve concordare con l'attributo TaskName
dell'elemento UsingTask corrispondente.
HelloWorld
Di seguito è riportata un'attività inline più concreta. 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. L'elemento Reference
dell'esempio è incluso solo ai fini della spiegazione.
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This simple inline task displays "Hello, world!" -->
<UsingTask
TaskName="HelloWorld"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Reference Include="System.Xml"/>
<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 richiamarla da un progetto come indicato di seguito.
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="HelloWorld.targets" />
<Target Name="Hello">
<HelloWorld />
</Target>
</Project>
Parametri di input e output
I parametri dell'attività inline sono elementi figlio di un 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ù degli attributi seguenti:
Required
è un attributo facoltativo che èfalse
per impostazione predefinita. Setrue
, il parametro è obbligatorio e deve avere un valore assegnato prima di chiamare l'attività.ParameterType
è un attributo facoltativo che èSystem.String
per 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 System.Convert.ChangeType. In altre parole, qualsiasi tipo che può essere passato a e da un'attività esterna.Output
è un attributo facoltativo che èfalse
per impostazione predefinita. Setrue
, il parametro deve avere un valore assegnato prima della restituzione da parte del 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 del tipo System.String.Files
è un parametro di input obbligatorio dell'elenco di elementi.Tally
è un parametro di output del tipo System.Int32.
Se l'elemento Code
ha come attributo Type
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 relative definizioni di parametro.
Esempio
L'attività inline seguente sostituisce ogni occorrenza di un token nel file specificato con il valore specificato.
<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="15.0">
<UsingTask TaskName="TokenReplace" TaskFactory="CodeTaskFactory" 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="C:\Project\Target.config" Token="$MyToken$" Replacement="MyValue"/>
</Target>
</Project>