75 votes

Comment remplacer une extension existante méthode

Je veux remplacer les méthodes d'extension inclus dans le .NET ou ASP MVC par mes propres méthodes.

Exemple

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

Est-il possible? Je ne peux pas utiliser le remplacement ou nouveau mot-clé.

122voto

Eric Lippert Points 300275

Mise à JOUR: Cette question a été l'objet de mon blog en décembre 2013. Merci pour la grande question!


Vous pouvez le faire, dans un sens. Mais je devrais commencer par parler brièvement le principe de conception de base de résolution de surcharge en C#. Toutes les résolution de surcharge est, bien sûr, sur la prise d'un ensemble de méthodes avec le même nom et en choisissant de définir l'unique meilleur membre de l'appeler.

Il y a beaucoup de facteurs impliqués dans la détermination de qui est la "meilleure" méthode; langues différentes d'utiliser un autre "mélange" des facteurs de comprendre cela. C# en particulier fortement poids "proximité" d'une méthode donnée pour le site d'appel. Si le choix entre une méthode dans une classe de base ou d'une nouvelle méthode applicable dans une classe dérivée, C# prend une dans la classe dérivée, car elle est la plus proche, même si l'un dans la classe de base est de toute autre manière une meilleure correspondance.

Et donc, nous courons vers le bas de la liste. Les classes dérivées sont plus proches que les classes de base. Les classes internes sont plus près que l'extérieur des classes. Méthodes dans la hiérarchie de classe sont plus proches que les méthodes d'extension.

Et nous en arrivons maintenant à votre question. La proximité d'une extension de la méthode dépend (1) de combien d'espaces de noms "out" n'avons-nous aller? et (2) ne nous trouvons la méthode d'extension via using ou était-il là, dans l'espace de noms? Par conséquent, vous pouvez influer sur la résolution de surcharge en modifiant en ce que l'espace de noms de votre statique de la classe d'extension apparaît, pour le mettre dans un plus proche de l'espace de noms pour le site d'appel. Ou, vous pouvez modifier votre using des déclarations, de mettre la using de l'espace de noms qui contient le désiré statique de la classe de plus près que les autres.

Par exemple, si vous avez

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

ensuite, il est ambigu qui est plus proche. Si vous voulez donner la priorité à la vôtre sur les leurs, vous pouvez choisir de faire ceci:

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

Et maintenant, lors de la résolution de surcharge va à résoudre l'extension de l'appel de méthode, les classes en Blorple d'abord, puis classes en FrobCo.MyExtensionNamespace, puis les classes en FrobCo, puis classes en BazCo.TheirExtensionNamespace.

Est-ce clair?

34voto

Andrew Hare Points 159332

Les méthodes d'Extension ne peut pas être remplacée, car ils ne sont pas les méthodes d'instance et qu'ils ne sont pas virtuels.

Le compilateur va se plaindre si vous importez à la fois l'extension metod par le biais des classes de l'espace de noms qu'il ne saura pas quelle est la méthode à appeler:

The call is ambiguous between the following methods or properties: ...

La seule façon de contourner cela est d'appeler votre méthode d'extension en utilisant une méthode statique de la syntaxe. Ainsi, au lieu de ceci:

a.Foo();

il vous suffit de faire ceci:

YourExtensionMethodClass.Foo(a);

6voto

Ondrej Svejdar Points 5039

Basé sur Eric le site (et le fait que les vues de code est rendu en ASP espace de noms), vous devez être en mesure de remplacer comme ça (au moins il travaille pour moi dans ASP.NET MVC4.0 Rasoir

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));
    }
  }
}

Notez l'espace de noms doit être "ASP".

4voto

James Black Points 26183

Les méthodes d'Extension sont en fait que des méthodes statiques, donc je ne sais pas comment vous pouvez les remplacer, mais si vous il suffit de les placer dans un espace de noms différent, alors vous pouvez appeler le vôtre à la place de celui que vous souhaitez remplacer.

Mais Matt Manela parle de la façon dont les méthodes d'instance ont la priorité sur les méthodes d'extension: http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/e42f1511-39e7-4fed-9e56-0cc19c00d33d

Pour plus d'idées sur les méthodes d'extension, vous pouvez regarder http://gen5.info/q/2008/07/03/extension-methods-nulls-namespaces-and-precedence-in-c/

Edit: j'ai oublié à propos de l'ambiguïté de la question, de sorte que votre meilleur pari est d'essayer de ne pas y compris les méthodes d'extension que vous souhaitez remplacer. Donc, vous devrez peut-être de ne pas utiliser le 'l'aide de la directive, mais il suffit de mettre dans le nom complet du paquet de certaines classes, ce qui pourrait résoudre le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X