C# Source Generators
A source generator is code that runs inside the compiler and adds new source files at build time. A program then uses the added code as if it had been written by hand.
A marked class and its generated part
The Sensor class is marked with the Report attribute. The second part is the file the generator adds at build time.
using System;
[AttributeUsage(AttributeTargets.Class)]
class ReportAttribute : Attribute
{
}
[Report]
partial class Sensor
{
public string Name = "Heat";
public int Level = 3;
}
// The file the generator adds at build time:
partial class Sensor
{
public string Describe()
{
return "Sensor has 2 fields";
}
}
class Program
{
static void Main(string[] args)
{
Sensor sensor = new Sensor();
Console.WriteLine(sensor.Describe());
}
}A second marked class
The same generator pattern serves a second marked class. Meter carries three fields, so its generated method reports three.
using System;
[AttributeUsage(AttributeTargets.Class)]
class ReportAttribute : Attribute
{
}
[Report]
partial class Meter
{
public string Name = "Flow";
public int Level = 5;
public int Range = 10;
}
// The file the generator adds at build time:
partial class Meter
{
public string Describe()
{
return "Meter has 3 fields";
}
}
class Program
{
static void Main(string[] args)
{
Meter meter = new Meter();
Console.WriteLine(meter.Describe());
}
}Example
using System;
[AttributeUsage(AttributeTargets.Class)]
class ReportAttribute : Attribute
{
}
[Report]
partial class Pump
{
public string Name = "Water";
public int Level = 2;
}
// The file the generator adds at build time:
partial class Pump
{
public string Describe()
{
return "Pump has 2 fields";
}
}
class Program
{
static void Main(string[] args)
{
Pump pump = new Pump();
Console.WriteLine(pump.Describe());
}
}Key points
- A generator implements the IIncrementalGenerator interface and is loaded by the compiler.
- A generator only adds files. It never changes a file that already exists.
- One generator can serve every class marked for it in a project.
- A partial class is a class whose parts can live in separate files.
- The compiler joins all parts of a partial class into one type.
- The added part is produced fresh at each build from the marked class.
In this example, the Pump class is marked with the Report attribute. Pump declares two fields. The generated part adds a Describe method to the same partial class. Main calls that method and prints its text.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What can a source generator do to a project at build time?