# CodegenCS **Repository Path**: DXFB/CodegenCS ## Basic Information - **Project Name**: CodegenCS - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-09 - **Last Updated**: 2026-05-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [![Nuget](https://img.shields.io/nuget/v/dotnet-codegencs?label=dotnet-codegencs)](https://www.nuget.org/packages/dotnet-codegencs) [![Downloads](https://img.shields.io/nuget/dt/dotnet-codegencs.svg)](https://www.nuget.org/packages/dotnet-codegencs) [![Nuget](https://img.shields.io/nuget/v/CodegenCS.Core?label=CodegenCS.Core)](https://www.nuget.org/packages/CodegenCS.Core) [![Downloads](https://img.shields.io/nuget/dt/CodegenCS.Core.svg)](https://www.nuget.org/packages/CodegenCS.Core) # CodegenCS Toolkit **CodegenCS is a Code Generation Toolkit where templates are written using plain C#**. It can generate code in any language (like C#, Javascript, Python, HTML, JSX, Java, SQL Scripts, CSHTML or any other) or any other text-based output (YAML, XML, Markdown, Terraform files, Dockerfile, etc). It's very easy to learn even if you're not familiar with C# or Visual Studio. It's a modern alternative to T4 Templates or generic templating engines like Razor/Liquid. The major objective of the toolkit is to make code-generation as easy as possible by providing tools and helpers, abstracting boilerplate and letting you focus only in template logic. **_"Simple things should be simple, and Complex things should be possible"_** (Alan Kay)

# Major Features ## Templates can be Markup-based or Programmatic Our templates use a [Hybrid model](https://github.com/Drizin/CodegenCS/tree/master/docs/Hybrid-Templates.md) where they can be written **programmatically** or using a **markup-language**, and you can mix both approaches (switch between them at any moment). This provides the **best balance between simplicity/maintenability and power** (templates can be concise/maintenable and you can still have complex logic when needed). - **Programmatic approach** is based on C# methods that explicitly write to output streams. It provides more control and is the best choice when you have complex logic that would be too confusing to be written as markup. - **Markup approach** is based on text-blocks written using string interpolation, where literals can be mixed with interpolated objects (variables or subtemplates) or with simple control-flow markup (`if`/`else`/`endif`, or `loops`). It provides simplicity/readability and is the best choice when you need to write literals/variables with little logic or no logic. It's similar to T4/Razor/Liquid/Handlebars but using pure C# and string interpolation - no need to learn a new syntax. To sum our hybrid model provides the best of both worlds: you can write templates using your favorite language (C#), in your favorite IDE (Visual Studio) with full **debugging** capabilities - and you can **leverage the power of .NET** and any **.NET library** (think LINQ, Dapper, Newtonsoft, Swashbuckle, RestSharp, Humanizer, etc.) ## Template Entrypoint Templates are C# programs so they should have an entrypoint method (named `Main()` or `TemplateMain()`). Methods (including entrypoint methods) can be "markup-based" os programmatic. A markup-based method is one that just return an interpolated string: ```cs class MyTemplate { FormattableString Main() => $"My first template"; } ``` A programmatic method can contain instructions and usually it writes explicitly to output streams: ```cs class MyTemplate { void Main(ICodegenOutputFile writer) { writer.Write($"My first template"); } } ``` ## Subtemplates (aka "partials") In a programmatic method we obviously can just invoke other methods to break down a template into smaller (and more organized blocks), but when you have a markup-based block (i.e. a large string) it's not so obvious how you can include a "subtemplate": In regular C# string interpolation we can only interpolate types that can be directly converted to string (`string`, `FormattableString`, `int`, `DateTime`, etc.), but in our magic TextWriter allows interpolating many other types including delegates (methods) so it's very easy to "embed" a subtemplate (a different method) right within an interpolated string. In the example below template starts with a markup entry-point and then it "escapes" from the markup and switches to a programmatic subtemplate (another method that might have more complex logic): ```cs class MyTemplate { string _ns = "MyNamespace"; FormattableString Main() => $$""" namespace {{ _ns }} { {{ WriteClass }} } """; void WriteClass(ICodegenOutputFile writer) { writer.WriteLine($$""" public class MyFirstClass { public void HelloWorld() { // ... } } """); } } ``` (`WriteClass` method will get the `ICodegenOutputFile` parameter automatically injected, as explained later). Switching back and forth between programmatic-mode (C# methods) or markup mode (large C# strings) is what enables our hybrid model. ## Indentation Control Our clever [Indent Control](https://github.com/Drizin/CodegenCS/tree/master/docs/Indent-Control.md) automatically captures the current indent (whatever number of spaces or tabs you have in current line) and will preserve it when you interpolate a large object (multiline) or when you interpolate a subtemplate. Generating code with the correct indentation (even if there are multiple nested levels) has never been so easy, and it works for both curly-bracket languages (C#/Javascript/Java/Golang/etc) and also for indentation-based languages (like Python). Explicit indent control is also supported. ## Command-line Tool (dotnet-codegencs) [dotnet-codegencs](https://github.com/Drizin/CodegenCS/tree/master/src/Tools/dotnet-codegencs/) is a cross-platform .NET tool (command-line tool). It's available for Windows/Linux/MacOS. Besides running templates, it can also be used to extract models from existing databases (**reverse engineer db schema**), or download our our [sample templates](https://github.com/CodegenCS/Templates). So if you want to quickly start generating code (e.g. based on your database) this is our **"batteries-included"** tool. You can run it manually or you can automate into your build pipeline. See [this example](/Samples/PrebuildEvent/RunTemplates.ps1) of a prebuild script that will install dotnet-codegencs, refresh a database schema, and run a template that generates POCOs. ## Visual Studio Extension Our [Visual Studio Extension](https://github.com/Drizin/CodegenCS/tree/master/src/VisualStudio/) allows running templates directly from Visual Studio. It's available for [Visual Studio 2022](https://marketplace.visualstudio.com/items?itemName=Drizin.CodegenCS) or [Visual Studio 2019/2017](https://marketplace.visualstudio.com/items?itemName=Drizin.CodegenCS-Compatibility). Output files are automatically added to the project (nested under the template item), so it's easy to use (but it doesn't have all features available in `dotnet-codegencs`). ## MSBuild Task Our [MSBuild Task](https://github.com/Drizin/CodegenCS/tree/master/src/MSBuild/) (nuget [here](https://nuget.org/packages/CodegenCS.MSBuild)) allows running templates on-the-fly during compilation. MSBuild Task `CodegenBuildTask` is automatically invoked during `BeforeCompile` target, will search for `*.csx` files in the project folder and will run each one. Files are physically saved to disk and will be automatically added to your compilation (and obviously you can add that to `.gitignore` if you want). ## Roslyn Source Generator Our [Source Generator](https://github.com/Drizin/CodegenCS/tree/master/src/SourceGenerator/) (nuget [here](https://nuget.org/packages/CodegenCS.SourceGenerator)) allows running templates on-the-fly during compilation. It's possible to render physical files on disk or just render in-memory (no need to add to source-control or put into ignore lists). ## Important Classes Before explaining more features it's important to first learn about 3 important classes: ### 1. CodegenTextWriter [CodegenTextWriter](https://github.com/Drizin/CodegenCS/tree/master/docs/CodegenTextWriter.md) is the **heart of CodegenCS toolkit**. We like to say it's a **TextWriter on Steroids** or a **Magic TextWriter** - but if you don't believe in magic you can say it's just a custom TextWriter that leverages string interpolation to automatically control indentation, and enriches string interpolation to allow interpolation of many types (like `Action<>` / `Func<>` delegates, `IEnumerable<>` lists) and special symbols (like `IF`/`ELSE`/`ENDIF`). This enriched string interpolation is what allows pure C# string interpolation to be used as a markup-language. `CodegenTextWriter` is just a text writer - it does not have any information about file path, and by default it writes to an in-memory `StringBuilder` (until output files are all saved at once). Check out [CodegenTextWriter documentation](https://github.com/Drizin/CodegenCS/tree/master/docs/CodegenTextWriter.md) to learn more about it, about how indenting is magically controlled, learn how to write clean and reusable templates using String Interpolation, Raw String Literals, delegates and IEnumerables, and learn all object types can be interpolated. ### 2. CodegenOutputFile Since `CodegenTextWriter` does not have any info about file paths, there is a subtype `CodegenOutputFile` which extends `CodegenTextWriter` by adding a relative path (where the file should be saved). Most tools use `(I)CodegenOutputFile` but actually the important logic is all in the base class `CodegenTextWriter`. ### 3. CodegenContext [`CodegenContext`](https://github.com/Drizin/CodegenCS/blob/master/src/Core/CodegenCS/CodegenContext.cs) is a container that can hold multiple instances of `CodegenOutputFile` (multiple output), and for simplicity it contains a default `DefaultOutputFile`. When a template is executed it gets an empty context and it can write either to the default file or it can create multiple files. ## Native Dependency Injection When a template is invoked there are many types that can be automatically injected into it: - `ICodegenTextWriter`: represents the "standard output stream" (for templates that write to a single output file). Check [CodegenTextWriter docs](https://github.com/Drizin/CodegenCS/tree/master/docs/CodegenTextWriter.md). - `ICodegenContext`: [CodegenContext](https://github.com/Drizin/CodegenCS/blob/master/src/Core/CodegenCS/CodegenContext.cs) is a container class that can hold multiple `ICodegenOutputFile` where each one will output to an individual file. (`CodegenOutputFile` is basically a `CodegenTextWriter` but extended to include the target file name). To write multiple files you can do like `context["Class1.js"].Write("something")`. - `ExecutionContext`: provides info about the template being executed (full path of `.cs` or `.dll`) - `VSExecutionContext`: provides info about the Visual Studio Project and Solution (`csproj` and `sln` paths) Only available when template is executed through Visual Studio Extension - `CommandLineArgs`: provides command-line arguments Only available when template is executed through CLI - `IModelFactory`: can be used to load (deserialize) any models from JSON files. No need to write boilerplate code (locating the file, reading from it, etc) - `ILogger`: templates can log (what they are doing) to this interface. Logs are automatically printed to console (if using dotnet-codegencs) or to Visual Studio Output Window Pane (if using VS Extension) The standard way of doing dependency injection is injecting the types into the class constructor (**constructor injection**), but if you have a very simple template and don't want it to have a class constructor you can also get the types injected into your `Main()` entrypoint method (**method injection**). Additionally if there are multiple constructors (or multiple overloads for `Main()` entrypoint) we pick the most specific overload (the one that matches all most number of models/arguments) - like other IoC containers do. Dependency injection is also available for interpolated delegates, which means that you can interpolate an `Action<>` (or `Func<>`) and the required types will be magically injected (even if caller method does not use those types). ## Models Templates are just C# so obviously they can read from any source (`.json`, `.txt`, `.yaml`, other files, databases, roslyn syntax tree, or anything else) - but [**models**](https://github.com/Drizin/CodegenCS/tree/master/src/Models) are our built-in mechanism for easily providing inputs to templates. `IModelFactory` can be injected into your templates and can be used to load (deserialize) any models from JSON files. Besides your own models you can use our [**ready-to-use models**](https://github.com/Drizin/CodegenCS/tree/master/src/Models) for common tasks (no need to reinvent the wheel): - [`DatabaseSchema`](https://github.com/Drizin/CodegenCS/tree/master/src/Models/CodegenCS.Models.DbSchema/DbSchema) represents the schema of a relational database. Your template can loop through tables, columns, indexes, etc. Our command-line tool (dotnet-codegencs) has a command to reverse engineer from existing MSSQL/PostgreSQL databases into a JSON model. - [`NSwag OpenApiDocument`](https://github.com/RicoSuter/NSwag/blob/master/src/NSwag.Core/OpenApiDocument.cs) represents an OpenAPI (Swagger) model. This is the standard model that everyone use - we just have a [factory](https://github.com/Drizin/CodegenCS/tree/master/src/Models/CodegenCS.Models.NSwagAdapter) to load it from file. Click [**here**](https://github.com/Drizin/CodegenCS/tree/master/src/Models) to learn more about our **Out-of-the-box Models** or learn [**How to Write a Custom Model**](https://github.com/Drizin/CodegenCS/blob/master/docs/CustomModels.md). ## Smart Compilation / Execution CodegenCS templates consist of a single `.cs` class that is compiled using Roslyn .NET Compiler and is executed using reflection, but our tools simplify both compilation and execution so that you only have to focus on template logic. During compilation (where a `.dll` is built based on the `.cs`) we automatically add some common namespaces and dll references so that you don't have to. So in most cases all you need is a `Template.cs` file with classes/methods - no need to worry about boilerplate code like `using` namespaces, adding nuget packages or creating a dummy `.csproj`. During execution we identify and invoke the best constructor (and do the dependency injection), then we identify the best entrypoint (should be named `Main()` or `TemplateMain()`, and can also have dependency injection) and invoke it. Entry-point method can follow C/Java/C# convention of being `void` or returning `int` (where a non-zero result means that an error happened and output should not be saved), or it can just return a `FormattableString` that gets rendered into default output file. ## Automatic Save By default the template outputs (`ICodegenContext`/ `ICodegenTextWriter`) are only in-memory, then after template execution the output file(s) are automatically saved (unless there were unhandled exceptions or non-zero return code). There are some smart defaults so that you can just focus on your template logic instead of writing boilerplate code: - Default output filename (unless specified in CLI with `--file `) is based on the template name (e.g. `Template.cs` will generate `Template.g.cs`) - Default folder (unless specified in CLI with `--folder `) is based on current folder (or based in template location if running from VS Extension). Relative paths are supported everywhere. ## Raw String Literals & Hassle-free Characters Escaping Most templating engines (including T4/Razor/Liquid) require characters-escaping to write common characters like `@`, `\`, `"`, `<#`, `#>`, `{{`, or `}}`. Escaping characters is annoying, error-prone, and prevents you from doing copy/paste (or text-comparison) between templates and real code. CodegenCS templates support [Raw String Literals](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/#raw-string-literals) which solves this problem like a charm - all you have to do is choose the right delimiters and then you don't have to worry anymore about escaping any character inside that block. ## No Mixed Indentation [Raw String Literals](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/#raw-string-literals) have another cool feature for multi-line blocks: "_In multi-line raw string literals, any whitespace to the left of the closing quotes is removed from all lines of the raw string literal_". This means that you can indent your multi-line raw string literals wherever they look better, and all whitespace to the left will be removed (the whole block is "docked to the left"). (If by now you're thinking that this leading whitespace is important for manually controlling the indentation of your templates it's probably because you haven't learned about how our [Indent Control](https://github.com/Drizin/CodegenCS/tree/master/docs/Indent-Control.md) works and makes manual indenting obsolete.) ## Templates Arguments and Options Templates can get `CommandLineArgs` which provides all command-line arguments provided, and they can use or validate those arguments. Another option to use custom arguments and options is using `System.CommandLine`, which abstracts the way arguments/options are validated and used - `dotnet-codegencs template run