Why You Can't使用webgrid的扩展方法

最近在ASP.NET论坛上出现了一个有趣的问题。在其中,提问者试图使用我的 Chop()扩展方法 限制WebGrid列中的字符数,但它将无法正常工作。起初,我有点难过,所以我自己尝试了,收到了错误消息:

'string'不包含'chop'的定义

 

呵呵?代码看起来很好:

        grid.Column(
            columnName : "Description",
            format: @<text>@item.Description.Chop(20)</text>
            )

..还有扩展方法被放置在App_code内的一个名为扩展的类中,所以它应该肯定地工作?然后我更接近地研究了错误消息,并看到了这一点:

例外详情: Microsoft.csharp.runtimeBinder.RuntimeBinderexception:'String'不包含“Chop”的定义

被抛出的例外 RuntimeBinder.,不是编译器。

webgridcolumn的参数 格式 参数占用是委托: fun<dynamic,object>。这意味着你必须通过一个 动态的 类型,然后在它返回之前完成某些内容 目的。在运行时解决了动态表达式。编译器不知道它是什么。

当您尝试使用扩展方法时,编译器将检查您尝试使用它的类型,以查看是否存在此类方法。如果没有。它将检查类型派生的任何基类,以查看它们是否包含具有正确名称的正式方法。如果该测试失败,则编译器将忙于查看任何引用的静态类,该类包含具有第一个参数的静态方法( 将调用方法的相同类型的扩展方法的一部分)。在印章方法的情况下,这将是一个 细绳。使用动态变量,该引用未作为其一部分传递"Payload"到runtimeBinder,因此无法在App_code文件夹中找到扩展方法。并且,在螺母的shell中,是您无法在动态上使用扩展方法的原因。

很棒,所以你能做什么?嗯,扩展方法仍然是一个静态方法,所以你可以称之为:

        grid.Column(
            columnName : "Description",
            format: @<text>@Extensions.Chop(item.Description, 20)</text>
            )

请注意,此问题不仅影响从传递给的查询中的项目 格式 WebGrid中的方法 - 它会影响您从数据库查询中获得的所有结果,因为 database.query. 方法返回A. Ienumerable.<动态的>。这意味着您不能简单地在此上下文中应用扩展方法:

@foreach(var item in data){
    @item.Description.Chop(30)<br />
}

您可以在上面的示例中完成的一件事(WebGrid之外)是将动态返回转换为强类型的返回。您可以使用Jeremy Skinners强烈键入WebMatrix.data的帮助器(http://www.jeremyskinner.co.uk/2011/01/24/strongly-typed-data-access-with-webmatrix-data/)。

如果您有问题尝试在WebGridColumn的格式参数中使用扩展方法,或者其他任何地方 动态的 从方法返回,希望你知道现在该做什么。但是这个例子还表明它仔细阅读了读取异常消息。