Recently, while creating some experimental C# source code generators (xafero/csharp-generators), I was just concatenating strings together. Like you do, you know, if things have to go very quickly. If you have a simple use case, use a formatted multi-line string or some template library like scriban. But I searched for a way to generate more and more complicated logic easily - like for example, adding raw SQL handler methods to my pre-generated DBSet-like classes for my ADO.NET experiment. You could now say: Use Roslyn and that's really fine if you look everything up in a website like SharpLab, which shows immediately the syntax tree of our C# code.
Example
Instead, I propose the following mutable model:
var unit = new CUnit { Usings = { "System" }, Members = {
new CClass { Name = "TestClass", Members = {
new CMethod { Name = "Main", IsStatic = true,
Params = { new CParam { Type = "string[]",
Name = "args" } }, Body = new() {
Statements = { "Console.WriteLine(args.Length)" }
} } } } } };
Console.WriteLine(unit.ToText());
which then produces code like this:
using System;
public class TestClass
{
public static void Main(string[] args)
{
Console.WriteLine(args.Length);
}
}
Why the heck?
The meta code model is mutable and allows for much easier manipulation of to-be-generated C# code than the Roslyn compiler provides. You can come back and modify parts of it freely, while also not having to remember if you put a semicolon at this position or not. The abstraction layer handles those minor details of the syntax tree instead! I hope to remove all unnecessary string allocations from my code and improve those C# source code generators over time.
Links
If you'd like to check it out on NuGet:
Coaster for generating C# code more easily
Cscg.Constants for constants by build scripts
Cscg.StubCreator for creating stubs out of C# XML doc
Cscg.Compactor for serializing POCOs to CBOR & XML
Cscg.AdoNet for EFCore-like pregenerated SQL wrappers
And finally, please click here if anything takes your fancy.