gpt4 book ai didi

c# - 为什么 RazorEngine 会动态编译带有匿名类型模型的模板?

转载 作者:太空狗 更新时间:2023-10-29 23:24:21 29 4
gpt4 key购买 nike

我注意到 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 组件的想法 a friend assembly到您的程序集(从而使内部结构可见),但这没有用。在Razor源码中,我们可以看到如下代码(在CompilerServiceBase.cs中):

 if (modelType != null)
{
if (CompilerServices.IsAnonymousType(modelType))
{
type.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(HasDynamicModelAttribute))));
}
}

然后(在 TemplateBaseOfT.cs 中):

HasDynamicModel = GetType().IsDefined(typeof(HasDynamicModelAttribute), true);

稍后在同一文件中使用:

if (HasDynamicModel && !(value is DynamicObject) && !(value is ExpandoObject))
model = new RazorDynamicObject { Model = value };
else
model = value;

是的 - 您的理解是正确的。此外,我们可以看到仅使内部结构可见是不够的,因为 Razor 将任何匿名类型视为动态类型(RazorDynamicObject extends DynamicObject)。如果包含程序集的内部可见,您可以尝试修补 Razor 代码以不将匿名类型视为动态类型。

不过,在那种情况下,我认为代码必须发出一个新的公共(public)类型,该类型包含与模型的匿名类型相同的属性,以便 Razor 生成的代码可以实例化该类型的实例。或者,您可以使用描述的 hack here为了允许方法返回匿名类型的实例。

关于c# - 为什么 RazorEngine 会动态编译带有匿名类型模型的模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14878997/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com