Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
RoslynCodeTaskFactory usa los compiladores Roslyn multiplataforma para generar ensamblajes de tarea en memoria para su uso como tareas integradas.
RoslynCodeTaskFactory las tareas tienen como destino .NET Standard y pueden funcionar en entornos de ejecución de .NET Framework y .NET Core, así como en otras plataformas, como Linux y macOS.
Nota:
RoslynCodeTaskFactory solo está disponible en MSBuild 15.8 y versiones posteriores. Las versiones de MSBuild siguen las versiones de Visual Studio, por lo que RoslynCodeTaskFactory está disponible en Visual Studio 2017, versión 15.8 y posteriores.
Estructura de una tarea en línea con RoslynCodeTaskFactory
RoslynCodeTaskFactory Las tareas en línea se declaran mediante el elemento UsingTask. La tarea insertada junto con el elemento UsingTask que la contiene normalmente se incluye en un archivo .targets y se importa en otros archivos de proyecto según sea necesario. Esta es una tarea básica en línea. Observe que no hace nada.
<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>
El UsingTask elemento del ejemplo tiene tres atributos que describen la tarea y el generador de tareas insertados que lo compila.
El
TaskNameatributo asigna un nombre a la tarea, en este caso,DoNothing.El
TaskFactoryatributo asigna un nombre a la clase que implementa el generador de tareas insertado.El
AssemblyFileatributo proporciona la ubicación del generador de tareas insertado. Como alternativa, puede usar elAssemblyNameatributo para especificar el nombre completo de la clase del generador de tareas en línea, que normalmente se encuentra en la caché global de ensamblados (GAC).
Los elementos restantes de la tarea DoNothing están vacíos y se proporcionan para ilustrar el orden y la estructura de una tarea en línea. En este artículo se presenta un ejemplo más sólido.
El elemento
ParameterGroupes opcional. Cuando se especifica, declara los parámetros de la tarea. Para obtener más información sobre los parámetros de entrada y salida, consulte Parámetros de entrada y salida más adelante en este artículo.El
Taskelemento describe y contiene el código fuente de la tarea.El
Referenceelemento especifica referencias a los ensamblados de .NET que usa en el código. Esto equivale a agregar una referencia a un proyecto en Visual Studio. ElIncludeatributo especifica la ruta de acceso del ensamblado al que se hace referencia.El
Usingelemento enumera los espacios de nombres a los que desea acceder. Este elemento es similar a lausingdirectiva de Visual C#. ElNamespaceatributo especifica el espacio de nombres que se va a incluir.
Reference y Using son elementos independientes del lenguaje. Las tareas en línea se pueden escribir en cualquiera de los lenguajes .NET CodeDom admitidos, por ejemplo, Visual Basic o Visual C#.
Nota:
Los elementos contenidos por el Task elemento son específicos del generador de tareas, en este caso, el generador de tareas de código.
Elemento de código
El último elemento secundario que se va a aparecer dentro del Task elemento es el Code elemento . El Code elemento contiene o busca el código que desea compilar en una tarea. Lo que se coloca en el Code elemento depende de cómo quiera escribir la tarea.
El Language atributo especifica el idioma en el que se escribe el código. Los valores aceptables son cs para C#, vb para Visual Basic.
El Type atributo especifica el tipo de código que se encuentra en el Code elemento .
Si el valor de
TypeesClass, elCodeelemento contiene código para una clase que deriva de la ITask interfaz .Si el valor de
TypeesMethod, el código define una sobrescritura del métodoExecutede la interfaz ITask.Si el valor de
TypeesFragment, el código define el contenido delExecutemétodo, pero no la firma ni lareturninstrucción .
El propio código suele aparecer entre un <![CDATA[ marcador y un ]]> marcador. Dado que el código está en una sección CDATA, no tiene que preocuparse por el escape de caracteres reservados, por ejemplo, "<" o ">".
Como alternativa, puede usar el Source atributo del Code elemento para especificar la ubicación de un archivo que contiene el código de la tarea. El código del archivo de origen debe ser del tipo especificado por el Type atributo . Si el Source atributo está presente, el valor predeterminado de Type es Class. Si Source no está presente, el valor predeterminado es Fragment.
Nota:
Si define la clase de tarea en un archivo de origen, el nombre de clase debe estar de acuerdo con el TaskName atributo del elemento UsingTask correspondiente.
Hola mundo
Esta es una tarea en línea más sólida con RoslynCodeTaskFactory. La tarea HelloWorld muestra "Hello, world!" en el dispositivo de registro de errores predeterminado, que suele ser la consola del sistema o la ventana Salida de Visual Studio. El Reference elemento del ejemplo se incluye solo para la ilustración.
<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>
Puede guardar la HelloWorld tarea en un archivo denominado HelloWorld.targets y, a continuación, invocarla desde un proyecto como se indica a continuación.
<Project>
<Import Project="HelloWorld.targets" />
<Target Name="Hello">
<HelloWorld />
</Target>
</Project>
Parámetros de entrada y salida
Los parámetros de tarea insertados son elementos secundarios de un elemento ParameterGroup. Cada parámetro toma el nombre del elemento que lo define. El código siguiente define el parámetro Text.
<ParameterGroup>
<Text />
</ParameterGroup>
Los parámetros pueden tener uno o varios de estos atributos:
Requiredes un atributo opcional que esfalsede forma predeterminada. Sitrueestá presente, el parámetro es necesario y debe tener un valor antes de ejecutar la tarea.ParameterTypees un atributo opcional que esSystem.Stringde forma predeterminada. Puede configurarse en cualquier tipo completamente calificado que sea un elemento o un valor que se pueda convertir en una cadena mediante System.Convert.ChangeType. (Es decir, cualquier tipo que se pueda pasar a una tarea externa y de vuelta).Outputes un atributo opcional que esfalsede forma predeterminada. Sitrue, el parámetro debe tener un valor antes de regresar del método Execute.
Por ejemplo
<ParameterGroup>
<Expression Required="true" />
<Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<Tally ParameterType="System.Int32" Output="true" />
</ParameterGroup>
define estos tres parámetros:
Expressiones un parámetro de entrada necesario de tipo System.String.Fileses un parámetro de entrada de lista de elementos obligatorio.Tallyes un parámetro de salida de tipo System.Int32.
Si el Code elemento tiene el Type atributo de Fragment o Method, las propiedades se crean automáticamente para cada parámetro. En RoslynCodeTaskFactory, si el Code elemento tiene el Type atributo de Class, no tiene que especificar el ParameterGroup, ya que se deduce del código fuente (esto es una diferencia con respecto a CodeTaskFactory). De lo contrario, las propiedades deben declararse explícitamente en el código fuente de la tarea y deben coincidir exactamente con sus definiciones de parámetros.
Ejemplo
La siguiente tarea en línea registra algunos mensajes y devuelve una cadena.
<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>
Estas tareas en línea pueden combinar rutas y obtener el nombre del archivo.
<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>
Proporcionar compatibilidad con versiones anteriores
RoslynCodeTaskFactory primero se puso a disposición en la versión 15.8 de MSBuild. Supongamos que quiere admitir versiones anteriores de Visual Studio y MSBuild, cuando RoslynCodeTaskFactory no estaba disponible, pero CodeTaskFactory era, pero quiere usar el mismo script de compilación. Puede usar un Choose constructo que utiliza la $(MSBuildVersion) propiedad para decidir en tiempo de compilación si usar RoslynCodeTaskFactory o volver a CodeTaskFactory, como en el siguiente ejemplo:
<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>