C #: Introducing Source Code Generators

image


We are pleased to present you a preview of the source code generators. This is a new feature that allows C # developers to analyze custom code and create new C # files, which in turn can be added to the compilation process. This happens with the help of a new component - the Source Generator.


To get started with generators, you will need the latest .NET 5 preview and Visual Studio preview . Note: Visual Studio is required to build the source code generator. This will be changed in the next preview of .NET 5.


What is a source code generator?


A source code generator is a piece of code that is executed at compile time, checks the program and creates additional files, which are then compiled with the rest of the code.


Here are two main features that it allows you to implement:


  • Get a compilation object that represents all the compiled user code. This object can be analyzed, and you can write code that works with syntactic and semantic models of compiled code, as is the case with modern analyzers.
  • 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 ?


Although source code generators are not technically a C # language feature, they are in the preview. Instead of introducing a new setting only for them, we decided that it would be easier to use the existing switch, which allows you to view the language features of the C # compiler.


All Articles