tutorial net mvc español ejemplo curso create asp c# asp.net-mvc

c# - net - Cómo anular un método de extensión existente



mvc c# (5)

ACTUALIZACIÓN: esta pregunta fue el tema de mi blog en diciembre de 2013 . Gracias por la gran pregunta!

Puedes hacer esto, en cierto sentido. Pero debería comenzar hablando brevemente sobre el principio de diseño básico de la resolución de sobrecarga en C #. La resolución de sobrecarga es, por supuesto, tomar un conjunto de métodos con el mismo nombre y elegir el mejor miembro único para llamar.

Hay muchos factores involucrados en determinar cuál es el "mejor" método; diferentes idiomas usan una "mezcla" de factores diferente para resolver esto. C # en particular pesa mucho la "cercanía" de un método dado al sitio de llamadas. Si se le da la opción entre un método aplicable en una clase base o un nuevo método aplicable en una clase derivada, C # toma uno en la clase derivada porque está más cerca, incluso si el de la clase base es de otra manera un mejor partido.

Y entonces corremos la lista. Las clases derivadas están más cerca que las clases base. Las clases internas están más cerca que las clases externas. Los métodos en la jerarquía de clases son más cercanos que los métodos de extensión.

Y ahora llegamos a tu pregunta. La cercanía de un método de extensión depende de (1) ¿cuántos espacios de nombres hay que "salir"? y (2) ¿encontramos el método de extensión using o estaba allí mismo en el espacio de nombres? Por lo tanto, puede influir en la resolución de sobrecarga cambiando en qué espacio de nombres aparece su clase de extensión estática, para ponerlo en un espacio de nombre más cercano al sitio de llamadas. O bien, puede cambiar sus declaraciones de using para poner el using del espacio de nombres que contiene la clase estática deseada más cerca que el otro.

Por ejemplo, si tiene

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

entonces es ambiguo que esté más cerca. Si quieres priorizar los tuyos sobre los suyos, puedes elegir hacer esto:

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

Y ahora, cuando la resolución de sobrecarga va a resolver la llamada al método de extensión, las clases en Blorple obtienen primero ir, luego las clases en FrobCo.MyExtensionNamespace , luego las clases en FrobCo , y luego las clases en BazCo.TheirExtensionNamespace .

¿Está claro?

Quiero reemplazar los métodos de extensión incluidos en .NET o ASP MVC framework por mis propios métodos.

Ejemplo

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

¿Es posible? No puedo usar la anulación o la nueva palabra clave.


Además de las respuestas existentes, también puede "anular" los métodos de extensión alterando la firma del método:

1.) Usa un tipo más específico

Esto solo puede usarse, por supuesto, si el tipo de objetivo es más específico que el del método de extensión existente. Además, podría ser necesario hacer esto para todos los tipos aplicables.

// "override" the default Linq method by using a more specific type public static bool Any<TSource>(this List<TSource> source) { return Enumerable.Any(source); } // this will call YOUR extension method new List<T>().Any();

2.) Agregar un parámetro ficticio

No tan lindo Además, esto requerirá que modifique las llamadas existentes para incluir el argumento ficticio.

// this will be called instead of the default Linq method when "override" is specified public static bool Any<TSource>(this IEnumerable<TSource> source, bool @override = true) { return source.Any(); } // this will call YOUR extension method new List<T>().Any(true);


Basado en la premisa de Eric (y el hecho de que el código de vistas se representa en el espacio de nombres ASP), usted debería poder anularlo así (al menos funciona para mí en 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)); } } }

Tenga en cuenta que el espacio de nombre debe ser "ASP".


Los métodos de extensión no pueden anularse porque no son métodos de instancia y no son virtuales.

El compilador se quejará si importa ambas clases de métodos de extensión a través del espacio de nombres, ya que no sabrá a qué método llamar:

La llamada es ambigua entre los siguientes métodos o propiedades: ...

La única forma de evitar esto es llamar a su método de extensión utilizando la sintaxis del método estático normal. Entonces en vez de esto:

a.Foo();

tendrías que hacer esto:

YourExtensionMethodClass.Foo(a);


Los métodos de extensión son básicamente métodos estáticos, por lo que no sé cómo puede anularlos, pero si los coloca en un espacio de nombre diferente, puede llamar al suyo en lugar del que desea reemplazar.

Pero Matt Manela habla sobre cómo los métodos de instancia tienen prioridad sobre los métodos de extensión: http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/e42f1511-39e7-4fed-9e56-0cc19c00d33d

Para obtener más ideas sobre los métodos de extensión, puede consultar http://gen5.info/q/2008/07/03/extension-methods-nulls-namespaces-and-precedence-in-c/

Editar: Olvidé el problema de la ambigüedad, por lo que la mejor opción es intentar no incluir los métodos de extensión que desea reemplazar. Por lo tanto, es posible que no necesite utilizar la directiva ''using'', sino que simplemente incluya todo el nombre del paquete de algunas clases, y esto podría resolver el problema.