Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de changer d’annuaire.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer d’annuaire.
RoslynCodeTaskFactory utilise les compilateurs Roslyn multiplateformes pour générer des assemblys de tâches en mémoire à utiliser comme tâches inline.
RoslynCodeTaskFactory les tâches ciblent .NET Standard et peuvent fonctionner sur les runtimes .NET Framework et .NET Core, ainsi que d’autres plateformes telles que Linux et macOS.
Remarque
RoslynCodeTaskFactory est disponible uniquement dans MSBuild 15.8 et versions ultérieures. Les versions de MSBuild suivent les versions de Visual Studio. RoslynCodeTaskFactory est donc disponible dans Visual Studio 2017 version 15.8 et versions ultérieures.
Structure d’une tâche inline avec RoslynCodeTaskFactory
RoslynCodeTaskFactory Les tâches inline sont déclarées à l’aide de l’élément UsingTask . La tâche inline et l’élément UsingTask qui le contient sont généralement inclus dans un .targets fichier et importés dans d’autres fichiers projet en fonction des besoins. Voici une tâche inline de base. Notez qu’il ne fait rien.
<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’élément UsingTask de l’exemple comporte trois attributs qui décrivent la tâche et la fabrique de tâches inline qui la compile.
L’attribut
TaskNamenomme la tâche, dans ce cas,DoNothing.L’attribut
TaskFactorynomme la classe qui implémente la fabrique de tâches inline.L’attribut
AssemblyFiledonne l’emplacement de la fabrique de tâches inline. Vous pouvez également utiliser l’attributAssemblyNamepour spécifier le nom complet de la classe de fabrique de tâches inline, qui se trouve généralement dans le Global Assembly Cache (GAC).
Les éléments restants de la DoNothing tâche sont vides et sont fournis pour illustrer l’ordre et la structure d’une tâche inline. Un exemple plus robuste est présenté plus loin dans cet article.
L’élément
ParameterGroupest facultatif. Lorsqu’elle est spécifiée, elle déclare les paramètres de la tâche. Pour plus d’informations sur les paramètres d’entrée et de sortie, consultez Les paramètres d’entrée et de sortie plus loin dans cet article.L’élément
Taskdécrit et contient le code source de la tâche.L’élément
Referencespécifie des références aux assemblys .NET que vous utilisez dans votre code. Cela équivaut à ajouter une référence à un projet dans Visual Studio. L’attributIncludespécifie le chemin d’accès de l’assembly référencé.L’élément
Usingrépertorie les espaces de noms auxquels vous souhaitez accéder. Cet élément ressemble à lausingdirective en Visual C#. L’attributNamespacespécifie l’espace de noms à inclure.
Reference et Using les éléments sont indépendant du langage. Les tâches inline peuvent être écrites dans l’un des langages .NET CodeDom pris en charge, par exemple Visual Basic ou Visual C#.
Remarque
Les éléments contenus par l’élément Task sont spécifiques à la fabrique de tâches, dans ce cas, la fabrique de tâches de code.
Élément Code
Le dernier élément enfant à afficher dans l’élément Task est l’élément Code . L’élément Code contient ou localise le code à compiler dans une tâche. Ce que vous placez dans l’élément Code dépend de la façon dont vous souhaitez écrire la tâche.
L’attribut Language spécifie la langue dans laquelle votre code est écrit. Les valeurs acceptables sont cs pour C#, vb pour Visual Basic.
L’attribut Type spécifie le type de code trouvé dans l’élément Code .
Si la valeur est
TypeClass, l’élément contient duCodecode pour une classe qui dérive de l’interface ITask .Si la valeur est
TypeMethod, le code définit une substitution de laExecuteméthode de l’interface ITask .Si la valeur est
TypeFragment, le code définit le contenu de laExecuteméthode, mais pas la signature ou l’instructionreturn.
Le code lui-même apparaît généralement entre un <![CDATA[ marqueur et un ]]> marqueur. Étant donné que le code se trouve dans une section CDATA, vous n’avez pas à vous soucier de l’échappement de caractères réservés, par exemple «< » ou «> ».
Vous pouvez également utiliser l’attribut Source de l’élément Code pour spécifier l’emplacement d’un fichier qui contient le code de votre tâche. Le code du fichier source doit être du type spécifié par l’attribut Type . Si l’attribut Source est présent, la valeur Type par défaut est Class. S’il Source n’est pas présent, la valeur par défaut est Fragment.
Remarque
Si vous définissez la classe de tâche dans un fichier source, le nom de la classe doit accepter l’attribut TaskName de l’élément UsingTask correspondant.
Salut tout le monde
Voici une tâche inline plus robuste avec RoslynCodeTaskFactory. La tâche HelloWorld affiche « Hello, world ! » sur l’appareil de journalisation des erreurs par défaut, qui est généralement la console système ou la fenêtre sortie de Visual Studio. L’élément Reference de l’exemple est inclus uniquement pour l’illustration.
<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>
Vous pouvez enregistrer la HelloWorld tâche dans un fichier nommé HelloWorld.targets, puis l’appeler à partir d’un projet comme suit.
<Project>
<Import Project="HelloWorld.targets" />
<Target Name="Hello">
<HelloWorld />
</Target>
</Project>
Paramètres d’entrée et de sortie
Les paramètres de tâche inline sont des éléments enfants d’un ParameterGroup élément. Chaque paramètre prend le nom de l’élément qui le définit. Le code suivant définit le paramètre Text.
<ParameterGroup>
<Text />
</ParameterGroup>
Les paramètres peuvent avoir un ou plusieurs de ces attributs :
Requiredest un attribut facultatif qui estfalsepar défaut. Sitrue, le paramètre est requis et doit avoir une valeur avant d’appeler la tâche.ParameterTypeest un attribut facultatif qui estSystem.Stringpar défaut. Il peut être défini sur n’importe quel type qualifié complet qui est un élément ou une valeur qui peut être converti en et à partir d’une chaîne à l’aide de System.Convert.ChangeType. (En d’autres termes, tout type pouvant être passé à une tâche externe et à partir d’une tâche externe).)Outputest un attribut facultatif qui estfalsepar défaut. Sitrue, le paramètre doit recevoir une valeur avant de retourner à partir de la méthode Execute.
Par exemple,
<ParameterGroup>
<Expression Required="true" />
<Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<Tally ParameterType="System.Int32" Output="true" />
</ParameterGroup>
définit ces trois paramètres :
Expressionest un paramètre d’entrée obligatoire de type System.String.Filesest un paramètre d’entrée de liste d’éléments requis.Tallyest un paramètre de sortie de type System.Int32.
Si l’élément Code a l’attribut Type ou FragmentMethod, les propriétés sont créées automatiquement pour chaque paramètre. Dans RoslynCodeTaskFactory, si l’élément Code a l’attribut TypeClass, vous n’avez pas à spécifier le ParameterGroup, car il est déduit du code source (il s’agit d’une différence par rapport CodeTaskFactoryà ). Sinon, les propriétés doivent être déclarées explicitement dans le code source de la tâche et doivent correspondre exactement à leurs définitions de paramètres.
Exemple :
La tâche inline suivante enregistre certains messages et retourne une chaîne.
<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>
Ces tâches inline peuvent combiner des chemins d’accès et obtenir le nom du fichier.
<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>
Fournir une compatibilité descendante
RoslynCodeTaskFactory la première est devenue disponible dans MSBuild version 15.8. Supposons que vous souhaitez prendre en charge les versions précédentes de Visual Studio et MSBuild, quand elle RoslynCodeTaskFactory n’était pas disponible, mais CodeTaskFactory que vous souhaitez utiliser le même script de génération. Vous pouvez utiliser une Choose construction qui utilise la propriété pour décider au moment de la $(MSBuildVersion) génération s’il faut utiliser ou RoslynCodeTaskFactory revenir à CodeTaskFactoryl’exemple suivant :
<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>