Search code examples
razorcode-generationrazorenginedotliquidscriban

Are there any issues with using Razor as a object-oriented code generator?


I've been experimenting with T4 templates to generate code for classes with methods and attributes. While it's serves my purpose, it's missing some highly desirable productivity features such as syntax highlighting, snippets and Templates on the Macintosh. The trend seems to be moving away from T4. I've encountered the same issues with other templating markup engine such as Scriban and Liquid,

Razor template appears to be an alternative, but it appears more geared towards generating HTML markup code. It's also unclear whether it's syntax collides with the target code output regions, and if outputting code as separate files is straightforward. Can Razor generate object-oriented code and operate outside the context of a web application?


Solution

  • Can Razor generate object-oriented code and operate outside the context of a web application? The short answer is yes, but I have done exactly this and I am not sure I would recommend doing it with Razor. I used RazorEngine to generate skeleton models and UI CrUD forms for a set of database tables. I pulled the table schema into an internal object model, did a bit of manipulation on it, and used that as the input model for the template. Here is a simplified example of my Razor template for creating a C# class:

    public partial class @(Model.ObjectName)
    {
        public @(Model.ObjectName) () 
        {
        }
    
        @foreach (UIGen.UITableCol Col in Model.Columns)
        {
    
            if (!Col.IsNullable)
            {
                <text>[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings=false)]</text>
            }
            if (Col.CSharpType == "string" && Col.MaxLength > 0)
            {
                <text>[StringLength(@Col.MaxLength)]</text>
            }
            @(Col.MVCPropertyAttributes)
            <text>[DisplayName("@(UIGen.Helpers.ToCSharpStringLiteral(Col.ColLabel))")]
                [Column]
                public @Col.CSharpType @Col.ColName { get; set; }
            </text>
        }
    }
    

    It worked for me, but the reasons I wouldn't whole-heartedly recommend it are:

    • Intellisense sometimes works, but frequently loses the plot. I too thought this would be the main advantage of using Razor. However I was doing this from a console app rather than using Razor in its natural environment of MVC, so YMMV.
    • You end up with a confusing mix of template C# and output C# interwined in the same file. For anything beyond a simple output you start to go curly bracket blind. (I was also generating lots server-side controllers and validation code.)
    • If you make the template neatly formatted your resulting C# isn't (lots of whitespace etc). Once the C# was generated I pushed it through dotnet-format to tidy it up.