如何覆盖现有的扩展方法
我想用自己的方法来replace.NET或ASP MVC框架中包含的扩展方法。
例
public static string TextBox(this HtmlHelper htmlHelper, string name) { ... }
可能吗? 我无法使用覆盖或新的关键字。
更新:这个问题是我的博客在2013年12月的主题 。 感谢您的好问题!
从某种意义上说,你可以做到这一点。 但是我应该先简单地谈谈C#中重载分辨率的基本devise原理。 当然,所有的重载解决scheme都是采用一组具有相同名称的方法,并从中select唯一的最佳成员来进行调用。
确定哪一个是最好的方法有很多因素, 不同的语言使用不同的“混合”因素来解决这个问题。 C#特别重视给定方法到呼叫站点的“接近度”。 如果在基类中的适用方法或派生类中的新适用方法之间进行select,则C#将在派生类中使用该方法,因为它更接近,即使基类中的方法更好比赛。
所以我们把这个名单放下。 派生类比基类更近。 内部类比外部类更近。 类层次中的方法比扩展方法更接近。
现在我们来谈谈你的问题。 扩展方法的紧密程度取决于(1)我们必须去“多less”命名空间? (2)我们是否通过using
名称空间或在名称空间中find扩展方法? 因此,您可以通过更改静态扩展类出现的名称空间来影响重载parsing,从而将其置于更靠近呼叫站点的命名空间中。 或者,你可以改变你的using
声明,把包含所需静态类的命名空间的using
比另一个更接近。
例如,如果你有
namespace FrobCo.Blorble { using BazCo.TheirExtensionNamespace; using FrobCo.MyExtensionNamespace; ... some extension method call }
那么这是更接近暧昧的。 如果你想优先考虑他们的,你可以select这样做:
namespace FrobCo { using BazCo.TheirExtensionNamespace; namespace Blorble { using FrobCo.MyExtensionNamespace; ... some extension method call }
而现在当重载决议去解决扩展方法调用时, Blorple
类首先进入,然后是FrobCo.MyExtensionNamespace
类,然后是FrobCo
类,然后是FrobCo
类。
这清楚吗?
扩展方法不能被覆盖,因为它们不是实例方法,也不是虚拟的。
如果您通过名称空间导入两个扩展方法类,编译器将会抱怨,因为它不知道要调用哪个方法:
以下方法或属性之间的调用是不明确的:…
唯一的解决办法是使用普通的静态方法语法来调用你的扩展方法。 所以,而不是这个:
a.Foo();
你将不得不这样做:
YourExtensionMethodClass.Foo(a);
扩展方法基本上只是静态方法,所以我不知道如何覆盖它们,但是如果你把它们放在不同的名字空间,那么你可以调用你的而不是你想要replace的那个。
但马特·马内拉谈到如何实例方法优先于扩展方法: http ://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/e42f1511-39e7-4fed-9e56-0cc19c00d33d
有关扩展方法的更多信息,请参阅http://gen5.info/q/2008/07/03/extension-methods-nulls-namespaces-and-precedence-in-c/
编辑:我忘了歧义问题,所以你最好的select是尝试不包括你想要replace的扩展方法。 所以,你可能不需要使用'using'指令,只需要放入一些类的整个包名就可以解决问题。
根据Eric的前提(以及视图代码被渲染到ASP命名空间的事实),你应该能够像这样覆盖它(至less在ASP.NET MVC4.0 Razor中适用于我
using System.Web.Mvc; namespace ASP { public static class InputExtensionsOverride { public static MvcHtmlString TextBox(this HtmlHelper htmlHelper, string name) { TagBuilder tagBuilder = new TagBuilder("input"); tagBuilder.Attributes.Add("type", "text"); tagBuilder.Attributes.Add("name", name); tagBuilder.Attributes.Add("crazy-override", "true"); return new MvcHtmlString(tagBuilder.ToString(TagRenderMode.Normal)); } } }
注意命名空间必须是“ASP”。