Skip to content

Instantly share code, notes, and snippets.

@occar421
Last active February 24, 2023 06:57
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save occar421/8ca46799c57f5fc9f5a0 to your computer and use it in GitHub Desktop.
Save occar421/8ca46799c57f5fc9f5a0 to your computer and use it in GitHub Desktop.
Code Generator, like T4 Template, with ASP.NET Razor and Roslyn

Razor Code Template

In T4 Template, ASPX .tt files are code seeds.
In Razor Code Template, Razor .cshtml files are seeds!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace RazorCodeTemplate.Runner
{
class Program
{
static void Main(string[] args)
{
var cshtml = "../../RazorSource.cshtml";
var service = new RazorCodeTemplate.TemplateService();
using (var reader = new StreamReader(cshtml))
using (var writer = new StreamWriter(cshtml + ".cs"))
{
try
{
var code = service.GenerateFromReader(reader);
writer.Write(code.Result);
}
catch (ApplicationException ex)
{
Console.WriteLine(ex.Message);
Console.ReadKey();
}
}
}
}
}
@using System;
@{
var message = "string";
}
using System;
using static System.Console;
namespace RazorCodeTemplateSample
{
class RazorResult
{
static void Main(string[] args)
{
@foreach (var c in message)
{
@:WriteLine('@c');
}
}
}
@foreach (var day in Enum.GetValues(typeof(DayOfWeek)))
{
<text>
class @(day.ToString() + "Content")
{
public string Name { get; } = "@day.ToString()";
}
</text>
}
}
using System;
using static System.Console;
namespace RazorCodeTemplateSample
{
class RazorResult
{
static void Main(string[] args)
{
WriteLine('s');
WriteLine('t');
WriteLine('r');
WriteLine('i');
WriteLine('n');
WriteLine('g');
}
}
class SundayContent
{
public string Name { get; } = "Sunday";
}
class MondayContent
{
public string Name { get; } = "Monday";
}
class TuesdayContent
{
public string Name { get; } = "Tuesday";
}
class WednesdayContent
{
public string Name { get; } = "Wednesday";
}
class ThursdayContent
{
public string Name { get; } = "Thursday";
}
class FridayContent
{
public string Name { get; } = "Friday";
}
class SaturdayContent
{
public string Name { get; } = "Saturday";
}
}
using System;
using static System.Console;
namespace RazorCodeTemplateSample
{
class T4Result
{
static void Main(string[] args)
{
WriteLine('s');
WriteLine('t');
WriteLine('r');
WriteLine('i');
WriteLine('n');
WriteLine('g');
}
}
class SundayContent
{
public string Name{ get; } = "Sunday";
}
class MondayContent
{
public string Name{ get; } = "Monday";
}
class TuesdayContent
{
public string Name{ get; } = "Tuesday";
}
class WednesdayContent
{
public string Name{ get; } = "Wednesday";
}
class ThursdayContent
{
public string Name{ get; } = "Thursday";
}
class FridayContent
{
public string Name{ get; } = "Friday";
}
class SaturdayContent
{
public string Name{ get; } = "Saturday";
}
}
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<#
var message = "string";
#>
using System;
using static System.Console;
namespace RazorCodeTemplateSample
{
class T4Result
{
static void Main(string[] args)
{
<#
foreach(var c in message)
{
#>
WriteLine('<#= c #>');
<#
}
#>
}
}
<#
foreach(var day in Enum.GetValues(typeof(DayOfWeek)))
{
#>
class <#= day.ToString() + "Content" #>
{
public string Name{ get; } = "<#= day.ToString() #>";
}
<#
}
#>
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RazorCodeTemplate
{
public abstract class TemplateBase
{
StringBuilder sb = new StringBuilder();
public abstract Task ExecuteAsync();
public void Write(object item)
{
sb.Append(item);
}
public void WriteLiteral(string literal)
{
sb.Append(literal);
}
public async Task<string> GenerateCodeAsync()
{
await ExecuteAsync();
return sb.ToString();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Reflection;
using Microsoft.AspNet.Razor;
using Microsoft.AspNet.Razor.Generator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace RazorCodeTemplate
{
public class TemplateService
{
public Task<string> GenerateFromReader(TextReader tr)
{
var language = new CSharpRazorCodeLanguage();
var host = new RazorEngineHost(language)
{
DefaultBaseClass = nameof(TemplateBase),
DefaultNamespace = nameof(RazorCodeTemplate),
DefaultClassName = "Generated",
GeneratedClassContext = new GeneratedClassContext(nameof(TemplateBase.ExecuteAsync), nameof(TemplateBase.Write), nameof(TemplateBase.WriteLiteral), new GeneratedTagHelperContext())
};
host.NamespaceImports.Add(nameof(RazorCodeTemplate));
var engine = new RazorTemplateEngine(host);
var generatorResults = engine.GenerateCode(tr);
if (!generatorResults.Success)
{
throw new ApplicationException(string.Join(Environment.NewLine, generatorResults.ParserErrors.Select(x => x.Message)));
}
var compilation = CSharpCompilation.Create(
assemblyName: "test",
syntaxTrees: new[] { CSharpSyntaxTree.ParseText(generatorResults.GeneratedCode) },
references: new[] { MetadataReference.CreateFromAssembly(typeof(Task).Assembly), MetadataReference.CreateFromAssembly(typeof(TemplateBase).Assembly) },
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);
using (var stream = new MemoryStream())
{
var emitResult = compilation.Emit(stream);
if (!emitResult.Success)
{
throw new ApplicationException(generatorResults.GeneratedCode + Environment.NewLine + string.Join(Environment.NewLine, emitResult.Diagnostics.Select(x => x.ToString())));
}
var assembly = Assembly.Load(stream.GetBuffer());//LoadFrom(nameof(RazorCodeTemplate) + ".dll");
foreach (var type in assembly.GetTypes())
{
Console.WriteLine(type.Name);
}
var instance = assembly.CreateInstance(host.DefaultNamespace + "." + host.DefaultClassName) as TemplateBase;
return instance.GenerateCodeAsync();
}
}
}
}
@raxuser100
Copy link

Great work does this operate standalone in VS2017?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment