24

给定以下字符串扩展方法

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

在 MVC4 Razor 视图中添加了 @using 语句

@using JHS.ExtensionMethods;

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

@Model.producer.phone.ToUSAPhone()

这导致以下错误

'string' does not contain a definition for 'ToUSAPhone'

我还尝试将命名空间放在 /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>

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

string test=producer.phone.ToUSAPhone();

似乎 MVC4 Razor 视图中没有对扩展方法的引用,但我不知道为什么?

4

5 回答 5

38

如果您尝试使用扩展方法的类型实际上是dynamic. 检查 CSharp RuntimeBinder 是否正在生成异常。如果是这样,您可以将该方法用作普通方法或花园静态方法:

@StringExtensions.ToUSAPhone(Model.producer.phone)

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

@(((string)Model.producer.phone).ToUSAPhone())

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

动态不支持扩展类型这一事实背后的原因是,在常规的非动态代码扩展方法中,通过对编译器已知的所有类进行全面搜索,以找到具有匹配扩展方法的静态类。搜索根据命名空间嵌套和每个命名空间中可用的“使用”指令按顺序进行。

这意味着为了正确解析动态扩展方法调用,DLR 必须在运行时知道源代码中的所有命名空间嵌套和“使用”指令是什么。没有方便的机制将所有这些信息编码到调用站点中。

于 2013-10-08T19:55:50.830 回答
1

这不仅仅是您调用扩展方法的类型是动态的,而是表达式中的任何内容都是动态的而不是强制转换的。

例如,这显然是动态的:

@ViewBag.ToJSON()

但我首先认为迈克的回答不适用于我,因为我正在这样做:

@(ViewBag.UserProfile.GetJSONProfile().ToJSON())

ToJSON()我的扩展方法在哪里,GetJSONProfile()只是返回object

我只是在间隔和愚蠢,但想提一下。

于 2014-04-25T20:42:11.030 回答
0

在将扩展的自定义命名空间添加到您的视图之前构建您的项目。

于 2013-10-09T13:21:41.517 回答
0

我遇到了完全相同的错误消息,但在我的情况下,以某种奇怪的方式,我通过放置“;”来修复它

那是什么

@{var subti = item.subtitle.Truncate(18)}

用 ; 固定

@{var subti = item.subtitle.Truncate(18);}

这也许可以帮助某人

于 2021-04-05T08:47:51.230 回答
0

这可能还有另一个微不足道的原因,它发生在我身上。

我在其中创建扩展的文件具有“内容”作为 VS 文件属性窗格上构建操作属性的值。

将其切换为“编译”立即解决了问题,自然......

于 2018-10-31T22:17:54.170 回答