The C# Source Generators revolution
Tags: csharp, sourcegenerator, preview
Published: 2021-08-14 00:07:20

---
title: The C# Source Generators revolution
published: true
description: How C# Source Generators can help get rid of reflection
tags: csharp, sourcegenerator, preview
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mz8xzlhuzx1q6gtzsjla.png
---

Along with .NET 5, Microsoft released C# Source Generators. 

And after creating my first generator, I consider it one of the coolest features .NET developers can use.

## But what are Source Generators?

They are C# programs that can analyze code, dynamically generate files and inject them into the build pipeline.

![Source Generator Pipeline Diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mz8xzlhuzx1q6gtzsjla.png)

## Use cases?!

* Generate C# classes from JSON
* Extend a POCO class with INotifyPropertyChanged 
* Generate builders from POCO classes
* Generate mapping extension methods to replace AutoMapper

## Super basic example

Each generator has 2 methods: one to analyze the existing code and one to generate new code.

```csharp
[Generator]
public class MyGenerator : ISourceGenerator
{
    public void Initialize(GeneratorInitializationContext context) { }

    public void Execute(GeneratorExecutionContext context) { }
}
```

To generate a C# class:
```csharp
var source = @"
namespace Dev.To {{
    public class Post {{
        public string Title {{ get; set; }}
    }}
}}";
context.AddSource("Post.cs", SourceText.From(source, Encoding.UTF8));
```

It might not seem much; however, think about what you can do with partial classes or extensions methods.

## How I tried to use them

If you work with .NET Core you might be familiar with `appsettings.json`.
We often need to create POCO classes representing the JSON and then register them in Startup to be injected later with `IOptions<>`.

Why don't we let source generators do the heavy lifting for us?

So, I create a preview NuGet that does exactly that!

* It reads `appsettings` content
* For each object property it creates a new C# class
* It creates a partial Startup class with a private `RegisterOptions` method that register the new classes with `services.Configure<PropertyName>(Configuration.GetSection(nameof(PropertyName)));`
* The only thing people need to do is making their `Startup` partial and call `RegisterOptions` in `ConfigureServices` method.

Given this JSON:
```json
{
  "MyOtherOptions": {
    "MyString": "any",
    "MyInt": 1,
    "MyDouble": 1.1,
    "MyBool": true,
    "MyObject": {
      "MyObjectString": "any"
    },
    "MyArray": [ "any" ]
  }
}
```

It generates these classes:

![Solution Tree Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v8moq3ynjm2kfm6rl45d.PNG)

Generated content:
```csharp
// MyOtherOptions.cs
public class MyOtherOptions
{
    public string MyString { get; set; }
    public int MyInt { get; set; }
    public double MyDouble { get; set; }
    public bool MyBool { get; set; }
    public MyObject MyObject { get; set; }
    public string[] MyArray { get; set; }
}

// Startup.Generated.cs
public partial class Startup
{
    private void RegisterOptions(IServiceCollection services)
    {
        services.Configure<MyOtherOptions>(Configuration.GetSection(nameof(MyOtherOptions)));
    }
}
```

## Final words

As you can see, there's a lot of potential behind this new feature. 

It will not replace Reflection completely but it can drastically improve performance for a lot of libraries!

However, since it's in preview, there are limitations, and things might change, so keep that in mind!


The code for my example can be found [here on GitHub](https://github.com/matteobortolazzo/dotnet-options-generator).

## Useful links

* [Introducing C# Source Generators](https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/)
* [Source Generators Cookbook](https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.cookbook.md)
* [The pain points of C# source generators](https://turnerj.com/blog/the-pain-points-of-csharp-source-generators)
* [Source generators colletion](https://github.com/amis92/csharp-source-generators)