我注意到RazorEngine.Compile()似乎以不同于其他类型的方式处理匿名类型。例如,请考虑下面的代码:为什么RazorEngine动态地使用匿名类型模型编译模板?
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通过生成动态模板来为匿名类型提供特殊支持。
因此我有两个问题: (1)我对此行为的理解是否正确? (2)有没有办法让剃刀为匿名模型输出强类型的模板?
如果不太了解剃刀是如何工作的,它似乎很可能。虽然匿名类型确实是常规的“强”类型,但在编译模板时,即使他们想要做这种类型的voodoo,也不可能引用具有确定性的类型(因为模板可能会被许多控制器调用)。 – millimoose 2013-02-14 16:12:16
但是,假设它们生成了一个类,它们可以为具有相同模式的本地匿名类型生成代码,并从一个类型映射到另一个类型。 – ChaseMedallion 2013-02-14 16:15:40
他们可以做所有的事情,但当它们的价值超过所需的努力时,它们中的大多数可以很容易地踢。在这种情况下,除了为了强类型而强制键入代码之外,没有什么好处。 – millimoose 2013-02-14 16:20:43