简体   繁体   中英

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:

  • 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. 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. 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 .

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.

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.

The difference is solely in the syntax you use to invoke the helper: ListArrayItemsInline is a normal method, but ListArrayItemsExternal is an extension method. If you attempt to invoke ListArrayItemsExternal as an extension method without casting the argument, then the compiler gives you this error message:

CS1973: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'ListArrayItemsExternal' but appears to have an extension method by that name. 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:

@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:

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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