C#
Summary - Source generators
Combine IIncrementalGenerator and AddSource to write a DTO generator.
Summary - Source generators
In this summary you will write a DTO generator: from a list of type names it filters those ending in Dto, generates a class definition for each, and adds them to a list with AddSource. This simulates the core flow of a real source generator.
The methods from earlier lessons (Where, Select, AddSource and foreach) come together here. The output is deterministic because list order is preserved.
DTO generator design
The static DtoGenerator class holds a Sources list, an AddSource method, and a Generate method. Generate filters the type names and calls AddSource(name + ".g.cs", $"public class {name} {{ }}") for each.
Main calls Generate with three names; only those ending in Dto are added to the source list. Then foreach prints the hint names.
Exercise Assemble the DTO generator
Define a static class DtoGenerator. Give it public static List<(string Hint, string Source)> Sources { get; } = new();, public static void AddSource(string hintName, string source) (with Sources.Add((hintName, source));), and public static void Generate(IEnumerable<string> typeNames). In Generate, loop foreach (var name in typeNames.Where(n => n.EndsWith("Dto"))) and call AddSource(name + ".g.cs", $"public class {name} {{ }}"). In Main, call DtoGenerator.Generate(new[] { "User", "UserDto", "OrderDto" }) and print each entry.Hint with foreach.
Show example solution
static class DtoGenerator { public static List<(string Hint, string Source)> Sources { get; } = new(); public static void AddSource(string hintName, string source) { Sources.Add((hintName, source)); } public static void Generate(IEnumerable<string> typeNames) { foreach (var name in typeNames.Where(n => n.EndsWith("Dto"))) AddSource(name + ".g.cs", $"public class {name} {{ }}"); } }. In Main: DtoGenerator.Generate(...), foreach (var entry in DtoGenerator.Sources) Console.WriteLine(entry.Hint);
Example solution:
using System;
using System.Collections.Generic;
using System.Linq;
static class DtoGenerator
{
public static List<(string Hint, string Source)> Sources { get; } = new();
public static void AddSource(string hintName, string source)
{
Sources.Add((hintName, source));
}
public static void Generate(IEnumerable<string> typeNames)
{
foreach (var name in typeNames.Where(n => n.EndsWith("Dto")))
{
AddSource(name + ".g.cs", $"public class {name} {{ }}");
}
}
}
class Program
{
static void Main()
{
DtoGenerator.Generate(new[] { "User", "UserDto", "OrderDto" });
foreach (var entry in DtoGenerator.Sources)
{
Console.WriteLine(entry.Hint);
}
}
}
Test yourself
-
Match each DTO generator step
- Where
- Filter names ending in Dto
- Select
- Generate a class definition
- AddSource
- Add generated code to the list
-
What is the purpose of a source generator?
- Do runtime reflection
- Read files
- Write tests
- Generate code at compile time
Show answer
Generate code at compile time — Correct. A source generator generates code at compile time.
-
Complete the Generate call
DtoGenerator.____(new[] { "User", "UserDto", "OrderDto" });
Show answer
DtoGenerator.Generate(new[] { "User", "UserDto", "OrderDto" });
Next lesson: Project design