在ASPNET Core 2.0之外使用“razor”

时间:2018-01-10 02:08:39

标签: razor asp.net-core asp.net-core-2.0

有没有人设法用aspnet核心2.0运行RAZOR?我想用它代替非常依赖于Visual Studio的T4模板。

我已经设法获得了C#中间代码,但我仍然无法再将其转换为字符串。

1)我是否走在正确的道路上?

2)如何执行生成的C#代码(并且是字符串形式)?如果可能的话,我希望它与ASPNET CORE一样。

C#(生成器代码适用于stackoverflow)

https://dotnetfiddle.net/T6Slzp

视图\ MyView.cshtml

@{
    string[] members = {"Jani", "Hege", "Kai", "Jim"};
    int i = Array.IndexOf(members, "Kai")+1;
    int len = members.Length;
    string x = members[2-1];
}

<html>
<body>
    <h3>The time is @DateTime.UtcNow</h3>
    @foreach (var person in members)
    {
        <p>@person</p>
    }

    <p>The number of names in Members are @len</p>
    <p>The person at position 2 is @x</p>
    <p>Kai is now in position @i</p>

    @{
        var j = 0;
        while (j < 5)
        {
            j += 1;
            <p>Line @j</p>
        }
    }
</body>
</html>

输出字符串(C#代码)

// <auto-generated/>
#pragma warning disable 1591
namespace RuntimeNamespace
{
    #line hidden
    using System;
    using System.Threading.Tasks;
    internal class TestView : BaseView
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
#line 1 "TestView.cshtml"

    string[] members = {"Jani", "Hege", "Kai", "Jim"};
    int i = Array.IndexOf(members, "Kai")+1;
    int len = members.Length;
    string x = members[2-1];

#line default
#line hidden
            WriteLiteral("\n<html>\n<body>\n    <h3>The time is ");
#line 10 "TestView.cshtml"
               Write(DateTime.UtcNow);

#line default
#line hidden
            WriteLiteral("</h3>\n");
#line 11 "TestView.cshtml"
     foreach (var person in members)
    {

#line default
#line hidden
            WriteLiteral("        <p>");
#line 13 "TestView.cshtml"
      Write(person);

#line default
#line hidden
            WriteLiteral("</p>\n");
#line 14 "TestView.cshtml"
    }

#line default
#line hidden
            WriteLiteral("\n    <p>The number of names in Members are ");
#line 16 "TestView.cshtml"
                                     Write(len);

#line default
#line hidden
            WriteLiteral("</p>\n    <p>The person at position 2 is ");
#line 17 "TestView.cshtml"
                              Write(x);

#line default
#line hidden
            WriteLiteral("</p>\n    <p>Kai is now in position ");
#line 18 "TestView.cshtml"
                         Write(i);

#line default
#line hidden
            WriteLiteral("</p>\n\n");
#line 20 "TestView.cshtml"

        var j = 0;
        while (j < 5)
        {
            j += 1;

#line default
#line hidden
            WriteLiteral("            <p>Line ");
#line 25 "TestView.cshtml"
               Write(j);

#line default
#line hidden
            WriteLiteral("</p>\n");
#line 26 "TestView.cshtml"
        }


#line default
#line hidden
            WriteLiteral("</body>\n</html>\n\n\n\n");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591

1 个答案:

答案 0 :(得分:2)

非常接近我会说。您可能还想查看Asp Net Core Scaffolding project on GitHub,因为它使用Razor的方式非常类似(这是Visual Studio for ASP .net Core项目中原生使用的脚手架工具)。

我的BaseView与您的略有不同,但看起来您应该只需执行以下操作:

Type compiledType = Compile(cSharpDocument.GeneratedCode);
BaseView razorTemplate = (BaseView)Activator.CreateInstance(compiledType);
var result = await razorTemplate.ExecuteAsync();
string output = razorTemplate.ToString();

CompileGetAssembly的实施方式如下:

private Type Compile(string content)
{
    SyntaxTree[] syntaxTrees = new[] { CSharpSyntaxTree.ParseText(content) };

    string dummyAssemblyName = Path.GetRandomFileName();

    CSharpCompilation compilation = CSharpCompilation.Create(dummyAssemblyName,
            options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
            syntaxTrees: syntaxTrees,
            references: _references);

    Assembly result = GetAssembly(compilation);

    Type type = result.GetExportedTypes().First();

    return type;
}

private static Assembly GetAssembly(Compilation compilation)
{
    using (MemoryStream ms = new MemoryStream())
    {
        EmitResult result = compilation.Emit(ms);

        if (!result.Success)
        {
            DiagnosticFormatter formatter = new DiagnosticFormatter();

            IEnumerable<string> errorMessages = result.Diagnostics
                                    .Where(d => d.IsWarningAsError || d.Severity == DiagnosticSeverity.Error)
                                    .Select(d => formatter.Format(d));

            throw new Exception($"Errors encountered whilst compiling assembly: {String.Join(Environment.NewLine, errorMessages)}");
        }

        ms.Seek(0, SeekOrigin.Begin);

        Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms);

        return assembly;
    }
}