简体   繁体   English

内联辅助方法如何以及为什么在运行时评估类型?

[英]How and why inline helper methods evaluating types at runtime?

As you know, we can create two types of Helper methods in ASP.NET MVC: 如您所知,我们可以在ASP.NET MVC中创建两种类型的Helper方法

  • Inline helper methods 内联辅助方法
  • External helper methods 外部帮助方法

And now, let's say I am passsing data from the controller to the view by using the ViewBag object. 现在,假设我使用ViewBag对象将数据从控制器传递到视图。 Like that: 像那样:

ViewBag.Fruits = new string[] {"Apple", "Orange", "Pear"};

And I have defined such inline helper method in the view: 我在视图中定义了这样的内联辅助方法

@helper ListArrayItemsInline(string[] items)
{
    ...
}

And here is an external helper method which takes a string array as an input: 这是一个外部辅助方法 ,它将字符串数组作为输入:

public static MvcHtmlString ListArrayItemsExternal(this HtmlHelper html, string[] list)
{
    ...
}

And the difference is that, I must cast ViewBag.Fruits to string[] if I want to use external one. 不同的是,如果我想使用外部的,我必须将ViewBag.Fruitsstring[] Yes, everything is right here. 是的,一切都在这里。 But, this is not the case with the inline one. 但是,内联的情况并非如此。 As I see, it evaluates types at runtime. 正如我所见,它在运行时评估类型。

// external one, we must cast 
@Html.ListArrayItemsExternal((string[])ViewBag.Fruits) 

// internal one, works just fine
@ListArrayItemsInline(ViewBag.Fruits)

Could you please explain me, how and why inline helper methods evaluating types at runtime? 能否请您解释一下,如何以及为什么内联辅助方法在运行时评估类型?

ViewBag property offers a flexible way to pass data to the view.The property of ViewBag is defined as dynamic type . ViewBag属性提供了一种将数据传递给ViewBag的灵活方式ViewBag属性定义为动态类型

public dynamic ViewBag{get;}

When a .NET compiler encounters a dynamic type,it emits a special chunk of code instead of simply evaluating the expression.Such special chunk of code passes the expression to the Dynamic Language Runtime(DLR) for a run-time evaluation. 当.NET编译器遇到动态类型时,它会发出一个特殊的代码块,而不是简单地计算表达式。这种特殊的代码块将表达式传递给动态语言运行时(DLR)以进行运行时评估。

In other words any expression based on the dynamic type is compiled at run time.Any member set or read out of ViewBag is always accepted by the compiler but not actually evaluated until execution. 换句话说,任何基于动态类型的表达式都是在运行时编译的。任何成员设置或从ViewBag中读出的成员总是被编译器接受,但在执行之前不会实际评估。

The difference is solely in the syntax you use to invoke the helper: ListArrayItemsInline is a normal method, but ListArrayItemsExternal is an extension method. 区别仅在于您用于调用帮助程序的语法ListArrayItemsInline是一种常规方法,但ListArrayItemsExternal是一种扩展方法。 If you attempt to invoke ListArrayItemsExternal as an extension method without casting the argument, then the compiler gives you this error message: 如果您尝试在不转换参数的情况下调用ListArrayItemsExternal作为扩展方法,则编译器会向您显示以下错误消息:

CS1973: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'ListArrayItemsExternal' but appears to have an extension method by that name. CS1973:'System.Web.Mvc.HtmlHelper'没有名为'ListArrayItemsExternal'的适用方法,但似乎有一个名称的扩展方法。 Extension methods cannot be dynamically dispatched. 无法动态分派扩展方法。 Consider casting the dynamic arguments or calling the extension method without the extension method syntax. 考虑转换动态参数或调用扩展方法而不使用扩展方法语法。

The error message suggests two options for resolving the error: 错误消息提示了解决错误的两个选项:

Option 1. Cast the dynamic argument: 选项1.转换动态参数:

@Html.ListArrayItemsExternal((string[])ViewBag.Fruits) 

Option 2. Call ListArrayItemsExternal using normal method syntax, in which case you don't have to cast the dynamic argument: 选项2.使用常规方法语法调用ListArrayItemsExternal ,在这种情况下,您不必转换动态参数:

MyHelpers.ListArrayItemsExternal(Html, ViewBag.Fruits)

The second option demonstrates that types can be resolved at run time for external helper methods. 第二个选项演示了可以在运行时为外部帮助程序方法解析类型。 You just have to use the right syntax. 您只需使用正确的语法。

As for why extension methods can't be dynamically dispatched, check out this answer by Eric Lippert . 至于为何无法动态调度扩展方法,请查看Eric Lippert的回答

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM