为什么在MVC4 Razor View中找不到扩展方法?

Chr*_*isP 23 c# asp.net asp.net-mvc razor asp.net-mvc-4

给出以下字符串扩展方法

namespace JHS.ExtensionMethods
{
  public static class StringExtensions
  {
    public static string ToUSAPhone(this String str)
    {
      return String.Format("{0:(###) ###-####}", Double.Parse(str));
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

@using语句被添加到MVC4 Razor视图中

@using JHS.ExtensionMethods;
Run Code Online (Sandbox Code Playgroud)

以下字符串值调用扩展方法

@Model.producer.phone.ToUSAPhone()
Run Code Online (Sandbox Code Playgroud)

这会导致以下错误

'string' does not contain a definition for 'ToUSAPhone'
Run Code Online (Sandbox Code Playgroud)

我还尝试将命名空间放在/ Views文件夹的web.config中并收到相同的错误.

<pages pageBaseType="System.Web.Mvc.WebViewPage">
  <namespaces>
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Optimization"/>
    <add namespace="System.Web.Routing" />
    <add namespace="JHS.ExtensionMethods"/>
  </namespaces>
</pages>
Run Code Online (Sandbox Code Playgroud)

我通过在C#类中调用相同的调用来验证扩展方法的工作原理

string test=producer.phone.ToUSAPhone();
Run Code Online (Sandbox Code Playgroud)

看来扩展方法的引用在MVC4 Razor视图中不可用,但我无法弄清楚为什么?

Mik*_*ind 36

如果您尝试使用扩展方法的类型实际上是a,则会发生这种情况dynamic.检查CSharp RuntimeBinder是否生成异常.如果是这样,您可以将该方法用作常用或园林静态方法:

@StringExtensions.ToUSAPhone(Model.producer.phone)
Run Code Online (Sandbox Code Playgroud)

或者您可以将值转换为字符串:

@(((string)Model.producer.phone).ToUSAPhone())
Run Code Online (Sandbox Code Playgroud)

根据Eric Lippert(前MSFT)的说法:

动态不支持扩展类型这一事实背后的原因是因为在常规的非动态代码扩展方法中,通过对编译器已知的所有类的完整搜索来工作,该静态类具有匹配的扩展方法.搜索按顺序进行,基于命名空间嵌套和每个命名空间中可用的"using"指令.

这意味着为了正确解析动态扩展方法调用,DLR必须在运行时知道所有命名空间嵌套和"using"指令都在源代码中.没有将所有信息编码到呼叫站点中的机制.

  • 我实际上并不确定它是RuntimeBinder错误.但错误信息和症状的描述肯定闻起来像一个.希望@ChrisP将回来并提供更多细节的确认. (2认同)