programing

기존 확장 메서드를 재정의하는 방법

nasanasas 2020. 12. 7. 08:13
반응형

기존 확장 메서드를 재정의하는 방법


.NET 또는 ASP MVC 프레임 워크에 포함 된 확장 메서드를 자체 메서드로 바꾸고 싶습니다.

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

가능합니까? 재정의 또는 새 키워드를 사용할 수 없습니다.


업데이트 :이 질문은 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,의 클래스 FrobCo,의 클래스, BazCo.TheirExtensionNamespace.

분명합니까?


확장 메서드는 인스턴스 메서드가 아니고 가상이 아니므로 재정의 할 수 없습니다.

컴파일러는 호출 할 메서드를 알지 못하므로 네임 스페이스를 통해 두 확장 메서드 클래스를 모두 가져 오면 불평합니다.

다음 메서드 또는 속성간에 호출이 모호합니다. ...

이 문제를 해결하는 유일한 방법은 일반 정적 메서드 구문을 사용하여 확장 메서드를 호출하는 것입니다. 그래서이 대신 :

a.Foo();

이 작업을 수행해야합니다.

YourExtensionMethodClass.Foo(a);

확장 메서드는 기본적으로 정적 메서드 일 뿐이므로 재정의 할 수있는 방법을 모르겠지만 다른 네임 스페이스에 넣으면 교체하려는 이름 대신 자신의 이름을 호출 할 수 있습니다.

그러나 Matt Manela는 인스턴스 메서드가 확장 메서드보다 우선 순위가 높은 방법에 대해 설명합니다. 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/참조하십시오.

Edit: I forgot about the ambiguity issue, so your best bet is to try not including the extension methods you want to replace. So, you may need to not use the 'using' directive but just put in the entire package name of some classes, and this could solve the problem.


Based on Eric premise (and the fact that views code is rendered into ASP namespace) you should be able to override it like this (at least it works for me in 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));
    }
  }
}

Note the namespace has to be "ASP".


In addition to the existing answers, you can also "override" extension methods by altering the method signature:

1.) Use a more specific type

This can only be used of course if the target type is more specific than that of the existing extension method. Also, it might be necessary to do this for all applicable types.

// "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.) Add a dummy parameter

Not as pretty. Also, this will require you to modify existing calls to include the dummy argument.

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

참고URL : https://stackoverflow.com/questions/1451099/how-to-override-an-existing-extension-method

반응형