Skip to content

Instantly share code, notes, and snippets.

@acple acple/Program.cs
Last active Aug 15, 2018

Embed
What would you like to do?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace RazorExecutor
{
class Program
{
static void Main(string[] args)
{
const string rootDir = "."; //
var fileSystem = RazorProjectFileSystem.Create(rootDir);
var razor = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder =>
builder.SetNamespace(nameof(RazorExecutor)).SetBaseType(nameof(RazorTemplate))
.ConfigureClass((_, node) => node.ClassName = "Generated_" + Guid.NewGuid().ToString("N")));
var engine = new RazorTemplateEngine(razor.Engine, fileSystem);
var items = fileSystem.EnumerateItems(rootDir);
var options = RazorCodeGenerationOptions.Create(builder => { builder.SuppressChecksum = true; builder.SuppressMetadataAttributes = true; });
var generated = items
.Select(engine.CreateCodeDocument)
.Select(x => { x.SetCodeGenerationOptions(options); return x; })
.Select(engine.GenerateCode)
.Select(x => x.GeneratedCode);
var tree = generated
.Select(x => CSharpSyntaxTree.ParseText(x))
.Select(x => x.GetCompilationUnitRoot().Members.First(s => s.IsKind(SyntaxKind.NamespaceDeclaration)).SyntaxTree);
var assemblies = GetAssemblies(Assembly.GetExecutingAssembly());
var compilation = CSharpCompilation.Create(
assemblyName: null,
syntaxTrees: tree,
references: assemblies.Select(x => MetadataReference.CreateFromFile(x)),
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var bytes = new MemoryStream())
{
var result = compilation.Emit(bytes);
if (!result.Success)
{
foreach (var diagnostics in result.Diagnostics)
Console.WriteLine(diagnostics);
return;
}
var results = Assembly.Load(bytes.ToArray()).GetTypes()
.Where(typeof(RazorTemplate).IsAssignableFrom)
.Select(Activator.CreateInstance)
.Cast<RazorTemplate>()
.Select(x => x.Result);
foreach (var output in results)
Console.WriteLine(output);
}
}
private static IEnumerable<string> GetAssemblies(Assembly assembly)
{
var cache = new HashSet<string>();
IEnumerable<string> Rec(Assembly current)
=> current.GetReferencedAssemblies()
.SelectMany(x => (cache.Add(x.FullName)) ? Rec(Assembly.Load(x)) : Enumerable.Empty<string>())
.Prepend(current.Location);
return Rec(assembly);
}
}
public abstract class RazorTemplate
{
private readonly StringBuilder builder;
public string Result { get; }
protected RazorTemplate()
{
this.builder = new StringBuilder();
Task.Run(this.ExecuteAsync).Wait();
this.Result = this.builder.ToString();
this.builder.Clear();
}
protected void Write(string value)
=> this.builder.Append(value);
protected void Write(object value)
=> this.builder.Append(value);
protected void WriteLiteral(string value)
=> this.builder.Append(value);
public abstract Task ExecuteAsync();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.