【发布时间】:2013-02-14 16:06:26
【问题描述】:
我注意到 RazorEngine.Compile() 似乎将匿名类型与其他类型区别对待。例如,考虑以下代码:
public static void Main()
{
try {
var model = new { s = default(string) };
RazorEngine.Razor.Compile("@Model.s.Length", model.GetType(), "a");
RazorEngine.Razor.Run(model, "a");
} catch (Exception ex) {
Console.WriteLine(ex); // RuntimeBinderException (Cannot perform runtime binding on a null reference)
}
try
{
var model = "";
RazorEngine.Razor.Compile(@"@Model.Length", model.GetType(), "b");
RazorEngine.Razor.Run(default(string), "b");
} catch (Exception ex) {
Console.WriteLine(ex); // NullReferenceException
}
try
{
var model = Tuple.Create(default(string));
RazorEngine.Razor.Compile(@"@Model.Item1.Length", model.GetType(), "c");
RazorEngine.Razor.Run(model, "c");
} catch (Exception ex) {
Console.WriteLine(ex); // NullReferenceException
}
try
{
var model = new Internal();
RazorEngine.Razor.Compile(@"@Model.S.Length", model.GetType(), "d");
RazorEngine.Razor.Run(model, "d");
} catch (Exception ex) {
Console.WriteLine(ex); // TemplateCompilationException (type Internal is not visible)
}
}
internal class Internal {
public string S { get; set; }
}
我的理解是:匿名类型是内部的,所以通常 Razor 不会处理它们。但是,Razor 通过生成动态模板来为匿名类型提供特殊支持。
因此我有两个问题: (1) 我对这种行为的理解是否正确? (2) 有没有办法让razor 为匿名模型输出强类型模板?
【问题讨论】:
-
在不了解 Razor 的工作原理的情况下,它看起来确实很有可能。虽然匿名类型确实是常规的“强”类型,但在编译模板时,实际上不可能肯定地引用使用的那个,即使他们想做这种巫术(因为可以从许多控制器调用模板。)
-
虽然他们生成了一个类,但他们可以只为具有相同架构的本地匿名类型生成代码,并从一种类型映射到另一种类型。
-
他们可以做各种各样的事情,但是当价值超过所需的努力时,他们会更容易下注。在这种情况下,除了为了强类型而对代码进行强类型之外,似乎没有什么好处。
-
另外,为了让我的猜测不那么疯狂:
new{a=""}.GetType().IsPublic返回false。因此,似乎在定义它们的任何范围之外都无法访问匿名类型。
标签: c# dynamic razor anonymous-types