What Are .NET Source Generators and How Do They Write Code
You use .NET Source Generators to help with boring tasks. They make new C# files when you build your project. This saves you time and helps you organize your code. You write less repeated code and keep your projects neat. Code that writes code lets you work on the important parts. You do not have to copy the same things again and again. If you are a developer, team lead, or architect, this tool helps you work faster. It also makes your code easier to take care of.
Key Takeaways
Source generators do boring coding jobs for you. This saves time and helps stop mistakes.
They work well with the Roslyn compiler. You get quick feedback and help from the IDE when you build.
Source generators help keep your code neat and tidy. This lets you spend more time on harder problems.
You can make strongly typed IDs and helpers that work at compile-time. This makes your code safer and faster.
Using source generators can make builds quicker. Your app can also run better.
Code That Writes Code
What Are Source Generators
Source generators are tools that help you make code faster in .NET projects. When you build your project, they look at your code and create new C# files for you. This happens while your code is being compiled, so you see the new files right away in your IDE. You get IntelliSense and error checks just like with your own code.
Source generators work with the Roslyn compiler. They check your code’s structure and syntax, then make new code that matches what you need. You do not have to write every line yourself. You use code that writes code for tasks that repeat a lot.
T4 text templates must run before your code is compiled. Source generators run during compilation. The output from source generators becomes part of your project right away.
Source generators can look at all the code being compiled. This lets you use advanced analysis, just like Roslyn Source Analyzers.
Here are some things source generators often do:
Add property change notifications like INotifyPropertyChanged
Make fast serialization and deserialization code
Create boilerplate for record types and equality methods
Add logging or validation to your code
Build dependency injection containers automatically
Make database access code for ORM
Create adapters and mapping for data transfer objects
Make logging and telemetry code that follows standards
Build type-safe HTTP client code
Manage enums and constants with string versions
Help with internationalization and localization using resources at compile time
Code that writes code helps keep your projects neat and easy to take care of. The files it makes are part of your project, but you do not have to handle them yourself.
Why Use Them
You pick source generators because they save time and help you avoid mistakes. When code writes code for you, you can work on harder problems. You do not need to copy and paste the same things again and again.
Source generators give you these benefits:
They automate boring code and save you time.
You make fewer mistakes by not repeating code.
You can work on tough tasks instead of easy ones.
They work with Roslyn, so you get code and IDE help right away.
The new code shows up instantly, so you see errors and tips fast.
Your code runs better because source generators can make it faster at compile time, like in System.Text.Json.
Source generators make your app run faster by cutting out extra work at runtime, using less memory, and making compilation better. They help developers by making boilerplate code for you, so your code is always neat and you make fewer mistakes. They keep your codebase clean by splitting up tasks, making code easier to read, and letting you do complex changes.
When you use code that writes code, your team keeps the codebase tidy and simple. Automating code generation helps people who take care of the project spot problems and handle changes. This makes your project easier to grow and maintain for a long time.
How They Work
Build Process Integration
You use .NET Source Generators to add new code while building. When you build, the generator connects to Roslyn. This lets you look at your code and make new files. You do not change your original files. The generator works in the background and adds new code. Source generators run when you compile. Your app does not slow down when running. You get feedback in your IDE right away. You see errors and tips fast. You spend less time on boring tasks. You focus more on important work. Code that writes code helps your workflow. It makes development easier.
Tip: Source generators work with the compiler pipeline. You see the new code like you wrote it, but you do not manage it.
Using source generators helps you work faster. Good design keeps builds quick and your IDE smooth. You can use the .NET 7 SDK API ForAttributeWithMetadataName()
for speed. Try using foreach
instead of LINQ to save memory. Incremental generators help you cache results and avoid slow builds.
Roslyn and Syntax Trees
The Roslyn compiler API lets you check and change C# code while compiling. You use Roslyn to read and study your code. You can see syntax trees, which show how your code is built. Syntax trees help you see spaces and formatting. Semantic models show what your code means. You can find types, namespaces, and symbol links. Both models help you gather info for making new code. You use these models to decide what code to create.
You can use context.Compilation.SyntaxTrees
to look at code models. This lets you see input and output for your generator. The Microsoft.CodeAnalysis.CSharp.SyntaxFactory
gives you tools to build syntax trees. You avoid problems with string joining and keep code safe.
Note: Generated code is added to the build without changing your files. The #line directive helps the compiler know where code came from, so you can debug easily.
Code that writes code uses Roslyn to check your project and make new files. You do not need to change your source files. The generator adds new code to the build, and you see it in your IDE. This keeps your codebase clean and easy to care for.
Build a Generator
Steps Overview
Making a .NET Source Generator has easy steps. First, you set up your project. Next, you look at your code and make new files. Here is what you do:
Set up a Source Generator Project
Make a new Class Library project fornetstandard2.0
. Add theMicrosoft.CodeAnalysis.CSharp
andMicrosoft.CodeAnalysis.Analyzers
NuGet packages.Implement a Custom Syntax Receiver
Write a class that finds syntax nodes you need. This class helps you pick where to make new files.Add a Marker Attribute
Use a special attribute to mark code you want the generator to use.Create the Incremental Source Generator
Build a generator class with the Roslyn API. Use theAddSource()
method to add new code.Build the Generator Pipeline
Set up steps for your generator. Collect info, check syntax, and make code.Generate the Source Code
Use what you found to make new C# files. Add these files when you compile your project.
Tip: Read Roslyn design docs and cookbook first. This helps you learn about incremental generators and avoid mistakes. Use
ForAttributeWithMetadataName
for speed. Do not use attribute inheritance to keep things fast.
Debugging and Testing
Debugging and testing help you check your source generator. You can use different tools and ways:
Put breakpoints in your generator and in code that uses new files.
Use Step Into in your IDE to follow the code.
Restart Visual Studio after changes for a clean test.
Use a
launchSettings.json
file to set up debugging.
You can add code like this to help with debugging:
#if DEBUG
if (!Debugger.IsAttached)
{
Debugger.Launch();
}
#endif
Testing your generator means checking output at each step. Track outputs, run the generator with a compilation, and compare results. Use a table to keep your checks organized:
Make sure outputs are saved and stay the same between runs. This helps your generator work well and stay fast.
Use Cases
Boilerplate Reduction
You might see the same code in many places. Source generators help you get rid of this extra work. They make code for you when you build your project. You can use them to do things like automate data access layer mappings. They also generate data transfer objects (DTOs) for APIs. They add XML comments for documentation too. You can make tasks easier, like using INotifyPropertyChanged
in WPF apps. They also help with mapping endpoints in ASP.NET Web APIs.
Make ORM mapping code for your database models.
Create client-side code from OpenAPI or Swagger specs.
Cut down on repeated service registration and endpoint mapping for handlers like
CreateNoteHandler
,GetNotesHandler
, andDeleteNoteHandler
.Add parameters and attributes to Blazor or Razor components.
When you automate boilerplate code, you can focus on creative work. You spend less time doing the same thing and more time making new features.
Strongly Typed IDs
Source generators can help you make strongly typed IDs. This helps you not make mistakes with entity identifiers. Instead of using types like Guid
for every ID, you can make types like ProjectId
or IssueId
. The generator adds properties and methods for these types. This makes your code safer.
Mark your struct with a
[StronglyTypedId]
attribute.Pick the backing-value type and make a custom JsonConverter if you need it.
Think about a method like
public Order GetOrderForUser(Guid orderId, Guid userId);
. If you mix up the order of the parameters, the compiler cannot catch it. Strongly typed IDs stop these bugs by using different types for each ID.
Compile-Time Helpers
Source generators make helpers when you build your code. These helpers help your app run faster. You do not need reflection, which can slow things down. The generator makes fast code for things like serialization, deserialization, and data validation.
[LoggerMessage(EventId = 9, Level = LogLevel.Trace, Message = "Fixed message", EventName = "CustomEventName")]
public partial void LogWithCustomEventName();
Make logging methods with dynamic log levels:
[LoggerMessage(EventId = 10, Message = "Welcome to {City} {Province}!")]
public partial void LogWithDynamicLogLevel(string city, LogLevel level, string province);
Use format specifiers for logging:
[LoggerMessage(EventId = 20, Level = LogLevel.Critical, Message = "Value is {Value:E}")]
public static partial void UsingFormatSpecifier(ILogger logger, double value);
Source generators help you make fast code for things like web APIs and games. Your code runs quicker and works better.
.NET Source Generators help you make code when you build. This makes builds faster and your app runs better. You also get type safety, so your code is safer. The new code shows up in your IDE. This helps you work in a clear and steady way. You can try a simple generator to see how it helps your project.
Tip: Try using incremental generators. Test your code and check how fast it runs for the best results.
Look at resources like Roslyn Succinctly or the Roslyn Cookbook to learn more. Open source projects and tutorials show you what you can do with the Roslyn API.
FAQ
What is a .NET Source Generator?
A .NET Source Generator is a tool that creates new C# code for you during the build process. You use it to automate tasks and reduce repeated code in your projects.
What kind of code can a source generator create?
You can use a source generator to make code for things like data models, logging helpers, or mapping classes. It helps you avoid writing the same code many times.
What do you need to start using source generators?
You need a .NET project and the right NuGet packages, like Microsoft.CodeAnalysis.CSharp
. You also need to write a generator class that tells the compiler what code to create.
What happens to the generated code?
The generated code appears in your project during build time. You see it in your IDE, and you can use it like any other code. You do not need to manage these files yourself.
What are the main benefits of using source generators?
Source generators save you time and help you avoid mistakes. You get cleaner code, fewer bugs, and faster builds. Your team can focus on important features instead of writing boilerplate.