一尘不染

如何覆盖现有的扩展方法

c#

我想用自己的方法替换.NET或ASP MVC框架中包含的扩展方法。

public static string TextBox(this HtmlHelper htmlHelper, string name)
{
   ...
}

可能吗?我不能使用override或new关键字。


阅读 254

收藏
2020-05-19

共1个答案

一尘不染

更新:这个问题是我2013年12月的博客主题。感谢您提出的好问题!


从某种意义上说,您可以做到这一点。但是,我首先要简单地谈谈C#中的重载解析的基本设计原理。当然,所有重载解决方案都是关于采用一组具有相同名称的方法并从中选择唯一的最佳成员来调用的。

确定哪种方法是“最佳”方法涉及很多因素。不同的语言使用不同的“混合”因素来解决这一问题。C#特别重视给定方法与调用站点的“接近性”。如果在基类中的适用方法或派生类中的新适用方法之间做出选择,则C#会在派生类中使用一个,因为它距离更近,即使基类中的每个方法都更好比赛。

因此,我们列出了这个清单。派生类比基类更近。内部类比外部类更接近。类层次结构中的方法比扩展方法更近。

现在我们来解决您的问题。扩展方法的紧密程度取决于(1)我们必须走多少个命名空间?(2)我们是通过using命名空间找到扩展方法还是在命名空间中找到扩展方法?因此,您可以通过更改静态扩展类的显示名称空间,并将其放在更靠近调用站点的名称空间中,从而影响重载解决方案。或者,您可以更改using声明,以将using包含所需静态类的名称空间的声明放得更近。

例如,如果您有

namespace FrobCo.Blorble
{
  using BazCo.TheirExtensionNamespace;
  using FrobCo.MyExtensionNamespace;
  ... some extension method call
}

那就更模糊了。如果您要优先于自己的,则可以选择执行以下操作:

namespace FrobCo
{
  using BazCo.TheirExtensionNamespace;
  namespace Blorble
  {
    using FrobCo.MyExtensionNamespace;
    ... some extension method call
  }

现在,当重载解析解决扩展方法调用时,Blorple首先进入中的类FrobCo.MyExtensionNamespace,然后进入中的类,然后进入中的类,然后再进入中的FrobCoBazCo.TheirExtensionNamespace

明白了吗?

2020-05-19