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.
RoslynCodeTaskFactory usa i compilatori Roslyn multipiattaforma per generare assembly di attività in memoria da usare come attività in linea.
RoslynCodeTaskFactory le attività sono destinate a .NET Standard e possono funzionare in runtime .NET Framework e .NET Core, nonché in altre piattaforme, ad esempio Linux e macOS.
Annotazioni
RoslynCodeTaskFactory è disponibile solo in MSBuild 15.8 e versioni successive. Le versioni di MSBuild seguono le versioni di Visual Studio, quindi RoslynCodeTaskFactory è disponibile in Visual Studio 2017 versione 15.8 e successive.
Struttura di un'attività inline con RoslynCodeTaskFactory
RoslynCodeTaskFactory le attività inline vengono dichiarate usando l'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à di base in linea. Si noti che non esegue alcuna operazione.
<Project>
<!-- 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>
</Project>
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 usare l'attributoAssemblyNameper specificare il nome completo della classe factory dell'attività inline, che si trova in genere nella Global Assembly Cache (GAC).
Gli elementi rimanenti dell'attività DoNothing sono vuoti e vengono forniti per illustrare l'ordine e la struttura di un'attività inline. Più avanti in questo articolo viene presentato un esempio più affidabile.
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. Equivale all'aggiunta di un riferimento a un progetto in Visual Studio. L'attributoIncludespecifica il percorso dell'assembly a cui si fa riferimento.L'elemento
Usingelenca gli spazi dei nomi a cui si vuole accedere. Questo elemento è simile allausingdirettiva in Visual C#. L'attributoNamespacespecifica lo spazio dei nomi da includere.
Reference e Using gli elementi sono indipendenti dalla lingua. Le attività inline possono essere scritte in uno dei linguaggi .NET CodeDom supportati, ad esempio Visual Basic o Visual 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
Se si definisce la classe task in un file di origine, il nome della classe deve accettare l'attributo dell'elemento TaskNameUsingTask corrispondente.
Salve, mondo
Ecco un'attività in linea più robusta con RoslynCodeTaskFactory. 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 nell'esempio è incluso solo per l'illustrazione.
<Project>
<!-- This simple inline task displays "Hello, world!" -->
<UsingTask
TaskName="HelloWorld"
TaskFactory="RoslynCodeTaskFactory"
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 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 utilizzando System.Convert.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 RoslynCodeTaskFactory, se l'elemento Code ha l'attributo Type di Class, non è necessario specificare ParameterGroup, poiché viene dedotto dal codice sorgente (si tratta di una differenza rispetto a CodeTaskFactory). In caso contrario, le proprietà devono essere dichiarate in modo esplicito nel codice sorgente dell'attività e devono corrispondere esattamente alle definizioni dei parametri.
Esempio
L'attività inline seguente registra alcuni messaggi e restituisce una stringa.
<Project>
<UsingTask TaskName="MySample"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildBinPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<Parameter1 ParameterType="System.String" Required="true" />
<Parameter2 ParameterType="System.String" />
<Parameter3 ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Log.LogMessage(MessageImportance.High, "Hello from an inline task created by Roslyn!");
Log.LogMessageFromText($"Parameter1: '{Parameter1}'", MessageImportance.High);
Log.LogMessageFromText($"Parameter2: '{Parameter2}'", MessageImportance.High);
Parameter3 = "A value from the Roslyn CodeTaskFactory";
]]>
</Code>
</Task>
</UsingTask>
<Target Name="Demo">
<MySample Parameter1="A value for parameter 1" Parameter2="A value for parameter 2">
<Output TaskParameter="Parameter3" PropertyName="NewProperty" />
</MySample>
<Message Text="NewProperty: '$(NewProperty)'" />
</Target>
</Project>
Queste attività inline possono combinare i percorsi e ottenere il nome del file.
<Project>
<UsingTask TaskName="PathCombine"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildBinPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<Paths ParameterType="System.String[]" Required="true" />
<Combined ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Combined = Path.Combine(Paths);
]]>
</Code>
</Task>
</UsingTask>
<UsingTask TaskName="PathGetFileName"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildBinPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<Path ParameterType="System.String" Required="true" />
<FileName ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
FileName = System.IO.Path.GetFileName(Path);
]]>
</Code>
</Task>
</UsingTask>
<Target Name="Demo">
<PathCombine Paths="$(Temp);MyFolder;$([System.Guid]::NewGuid()).txt">
<Output TaskParameter="Combined" PropertyName="MyCombinedPaths" />
</PathCombine>
<Message Text="Combined Paths: '$(MyCombinedPaths)'" />
<PathGetFileName Path="$(MyCombinedPaths)">
<Output TaskParameter="FileName" PropertyName="MyFileName" />
</PathGetFileName>
<Message Text="File name: '$(MyFileName)'" />
</Target>
</Project>
Garantire la compatibilità con le versioni precedenti
RoslynCodeTaskFactory è diventato disponibile per la prima volta in MSBuild versione 15.8. Si supponga di voler supportare le versioni precedenti di Visual Studio e MSBuild, quando RoslynCodeTaskFactory non era disponibile, ma CodeTaskFactory lo era, ma si voleva usare gli stessi script di compilazione. È possibile usare un Choose costrutto che utilizza la $(MSBuildVersion) proprietà per decidere durante la compilazione se utilizzare il RoslynCodeTaskFactory o fare uso di CodeTaskFactory come alternativa, come nell'esempio seguente.
<Project Sdk="Microsoft.NET.Sdk" DefaultTargets="RunTask">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<Choose>
<When Condition=" '$(MSBuildVersion.Substring(0,2))' >= 16 Or
('$(MSBuildVersion.Substring(0,2))' == 15 And '$(MSBuildVersion.Substring(3,1))' >= 8)">
<PropertyGroup>
<TaskFactory>RoslynCodeTaskFactory</TaskFactory>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<TaskFactory>CodeTaskFactory</TaskFactory>
</PropertyGroup>
</Otherwise>
</Choose>
<UsingTask
TaskName="HelloWorld"
TaskFactory="$(TaskFactory)"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup />
<Task>
<Using Namespace="System"/>
<Using Namespace="System.IO"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
Log.LogError("Using RoslynCodeTaskFactory");
]]>
</Code>
</Task>
</UsingTask>
<Target Name="RunTask" AfterTargets="Build">
<Message Text="MSBuildVersion: $(MSBuildVersion)"/>
<Message Text="TaskFactory: $(TaskFactory)"/>
<HelloWorld />
</Target>
</Project>