C #: Présentation des générateurs de code source

image


Nous sommes heureux de vous présenter un aperçu des générateurs de code source. Il s'agit d'une nouvelle fonctionnalité qui permet aux développeurs C # d'analyser du code personnalisé et de créer de nouveaux fichiers C #, qui à leur tour peuvent être ajoutés au processus de compilation. Cela se produit à l'aide d'un nouveau composant - le générateur de source.


Pour commencer avec les générateurs, vous aurez besoin de la dernière prévisualisation .NET 5 et de la prévisualisation Visual Studio . Remarque: Visual Studio est requis pour créer le générateur de code source. Cela sera modifié dans la prochaine prévisualisation de .NET 5.


Qu'est-ce qu'un générateur de code source?


Un générateur de code source est un morceau de code qui est exécuté pendant la compilation, vérifie le programme et crée des fichiers supplémentaires, qui sont ensuite compilés avec le reste du code.


Voici deux fonctionnalités principales qu'il vous permet de mettre en œuvre:


  • Obtenez un objet de compilation qui reprĂ©sente tout le code utilisateur compilĂ©. Cet objet peut ĂŞtre analysĂ© et vous pouvez Ă©crire du code qui fonctionne avec des modèles syntaxiques et sĂ©mantiques de code compilĂ©, comme c'est le cas avec les analyseurs modernes.
  • C# , . , .

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


:


image


.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 ?


Bien que les générateurs de code source ne soient pas techniquement une fonctionnalité du langage C #, ils sont dans l'aperçu. Au lieu d'introduire un nouveau paramètre uniquement pour eux, nous avons décidé qu'il serait plus facile d'utiliser le commutateur existant, qui vous permet de visualiser les fonctionnalités du langage du compilateur C #.


All Articles