DEV Community

xafero
xafero

Posted on

Generating C# code programmatically

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());
Enter fullscreen mode Exit fullscreen mode

which then produces code like this:

using System;

public class TestClass
{
    public static void Main(string[] args)
    {
        Console.WriteLine(args.Length);
    }
}
Enter fullscreen mode Exit fullscreen mode

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:

And finally, please click here if anything takes your fancy.

Top comments (0)