C #: Introducción de generadores de código fuente

imagen


Nos complace presentarle una vista previa de los generadores de código fuente. Esta es una nueva característica que permite a los desarrolladores de C # analizar código personalizado y crear nuevos archivos de C #, que a su vez se pueden agregar al proceso de compilación. Esto sucede con la ayuda de un nuevo componente: el generador de origen.


Para comenzar con los generadores, necesitará la última vista previa de .NET 5 y la vista previa de Visual Studio . Nota: Se requiere Visual Studio para construir el generador de código fuente. Esto se cambiará en la próxima vista previa de .NET 5.


¿Qué es un generador de código fuente?


Un generador de código fuente es un fragmento de código que se ejecuta durante la compilación, comprueba el programa y crea archivos adicionales, que luego se compilan con el resto del código.


Aquí hay dos características principales que le permite implementar:


  • Obtenga un objeto de compilación que represente todo el código de usuario compilado. Este objeto puede analizarse y puede escribir código que funcione con modelos sintácticos y semánticos de código compilado, como es el caso de los analizadores modernos.
  • C# , . , .

. , , C# . Roslyn, , C#.


:


imagen


.NET Standard 2.0, , .NET Standard.


, .


, .


— , , , .


: , IL (IL weaving) MSBuild. .


— .NET. . .


, ASP.NET Core - , , razor . , : - , , , , . , .


— . .


, . MSBuild C# ( CSC) . , . MSBuild, , .


, — "-" (“stringly-typed”) API. , , ASP.NET Core razor. . , , .


API . -, .


Ahead-of-Time (AOT)


linker-based AOT-. , System.Text.Json, System.Text.RegularExpressions; ASP.NET Core WPF, / .


NuGet . .NET, "" ( “linkability”) AOT . OSS , .NET.


Hello World-


, .


, “Hello World” , . :


public class SomeClassInMyCode
{
    public void SomeMethodIHave()
    {
        HelloWorldGenerated.HelloWorld.SayHello(); 
        //  Console.WriteLine("Hello World!")     
    }
}

, :


1. .NET.


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <LangVersion>preview</LangVersion>
  </PropertyGroup>

  <PropertyGroup>
    <RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json ;$(RestoreAdditionalProjectSources)</RestoreAdditionalProjectSources>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.6.0-3.20207.2" PrivateAssets="all" />
    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.0.0-beta2.final" PrivateAssets="all" />
  </ItemGroup>

</Project>

2. C#, .


using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;

namespace MyGenerator
{
    [Generator]
    public class MySourceGenerator : ISourceGenerator
    {
        public void Execute(SourceGeneratorContext context)
        {
            // TODO -     
        }

        public void Initialize(InitializationContext context)
        {
             //     
        }
    }
}

Microsoft.CodeAnalysis.Generator Microsoft.CodeAnalysis.ISourceGenerator.


3. .


using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;

namespace SourceGeneratorSamples
{
    [Generator]
    public class HelloWorldGenerator : ISourceGenerator
    {
        public void Execute(SourceGeneratorContext context)
        {

            // ,       
            var sourceBuilder = new StringBuilder(@"

using System;
namespace HelloWorldGenerated
{
    public static class HelloWorld
    {
        public static void SayHello() 
        {
            Console.WriteLine(""   !"");
            Console.WriteLine(""       "");
");

           //  ,       
            var syntaxTrees = context.Compilation.SyntaxTrees;
            //        ,   
            foreach (SyntaxTree tree in syntaxTrees)
            {
                sourceBuilder.AppendLine($@"Console.WriteLine(@"" - {tree.FilePath}"");");
            }
            //   
            sourceBuilder.Append(@"
        }
    }
}");
            //      
            context.AddSource("helloWorldGenerator", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8));
        }

        public void Initialize(InitializationContext context)
        {
              //     
        }
    }
}

4. LangVersion .


<!--        -->
<PropertyGroup>
  <LangVersion>preview</LangVersion>
</PropertyGroup>

<!--   ItemGroup,       -->
<ItemGroup>
<!--   ,    "" ProjectReference. 
   'OutputItemType'  'ReferenceOutputAssmbly'. -->
    <ProjectReference Include="path-to-sourcegenerator-project.csproj" 
                      OutputItemType="Analyzer"
                      ReferenceOutputAssembly="false" />
</ItemGroup>

Roslyn, .


Visual Studio , . , :


public class SomeClassInMyCode
{
    public void SomeMethodIHave()
    {
        HelloWorldGenerated.HelloWorld.SayHello(); 
        //  Console.WriteLine("Hello World!")     
    }
}

: Visual Studio, IntelliSense


:


  • , , INotifyPropertyChanged,
  • , SourceGeneratorContext,
  • JSON- . .

Source Generators Cookbook.
GitHub.


, — , IntelliSense , Visual Studio.



. — . API . C# 9, API , .


C# : ! .NET , C# – . , - .


:



, .



Visual Studio , “ 1.0”. , . .NET 5 . , API, - OSS.


. , . .


FAQ


, . .


— , ?


— , , , . , . , , . , - , .


F#?


F#. . , F# , . — , C#, , C# .


?


. — . “”, . .


?


, . , , . C#, . -.


/ ?


. , / . , C#.


?


C# 9. , .


TFM ?


. .NET Standard 2.0 TFM . .NET Standard 2.0.


Visual Basic F#?


#. , . VB . F# — .


?


, . VB F# , , . . . , , .


Intellisense ? Visual Studio , ?


Visual Studio. . Visual Studio .


Visual Studio?


Visual Studio.


?


NuGet, , . .


Microsoft ?


. . , Microsoft .


LangVersion ?


Aunque los generadores de código fuente no son técnicamente una característica del lenguaje C #, están en la vista previa. En lugar de introducir una nueva configuración solo para ellos, decidimos que sería más fácil usar el conmutador existente, que le permite ver las características del lenguaje del compilador de C #.


All Articles