2013-09-02 2 views
4

asp.net 웹 페이지가 있습니다. 다음은이 페이지를 구현하는 클래스입니다.null을 반환하는 GetMethod

public partial class _Default : System.Web.UI.Page 
    { 
     private readonly string delegateName = "DynamicHandler"; 

     protected void Page_Load(object sender, EventArgs e) 
     { 
      EventInfo evClick = btnTest.GetType().GetEvent("Click"); 

      Type tDelegate = evClick.EventHandlerType; 

      MethodInfo method = this.GetType().GetMethod("DynamicHandler", 
       BindingFlags.NonPublic | BindingFlags.Instance); 

      Delegate d = Delegate.CreateDelegate(tDelegate, this, method); 

      MethodInfo addHandler = evClick.GetAddMethod(); 
      Object[] addHandlerArgs = { d }; 
      addHandler.Invoke(btnTest, addHandlerArgs); 


     } 

     private void DynamicHandler(object sender, EventArgs e) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

동적으로 이벤트 처리기를 연결하려고합니다. 어떤 이유로 든 method은 null로 남아 있으며 그 이유를 알 수 없습니다. 나는 이것을 여러 번 해본 적이 있는데, 나는 무엇이 실종되었는지 알 수 없다.

편집

: 나는 this.GetType() 페이지 ASP.default_aspx의 유형을 반환이 아닌 실제의 형태 페이지를 구현하는 것을 발견했다. 난 정말

당신이 당신의 편집에 발견 한 것처럼
+1

왜 핸들러를 직접 추가하지 않습니까? 'btnTest.Click + = DynamicHandler; ' –

+0

@DanielHilgarth - 위임 메서드 이름을 관리 시스템의 문자열로 가져 왔기 때문에. –

+0

그럴 경우 : 여기에 표시된 샘플 코드를 테스트 해 보셨습니까? 정말 문제를 재현합니까? 왜냐하면 나에게 보여준 코드가 좋아 보인다. –

답변

4

는 실제로 ASPX 페이지가 가 (코드가있는) _Default에서을 상속하는 클래스로 컴파일됩니다 ...이 극복하는 방법을 모르겠어요. 따라서 private 대신 DynamicHandler (이상)을 protected 개 생성해야합니다.

BindingFlags.FlattenHierarchy도 지정

this.GetType().GetMethod("DynamicHandler", 
      BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); 

+0

이렇게하면됩니다. 또한,'this.GetType(). BaseType'도 같은 이유로 작동한다는 것을 알게되었습니다. 고맙습니다! –

+1

'BindingFlags.FlattenHierarchy'는 비 정적 멤버와 관련된 ***이 아닌 ***입니다. 상속 된 비공개 정적 멤버가 기본적으로 선택됩니다. (원하지 않는다면'BindingFlags.DeclaredOnly'를 사용하십시오.)'BindingFlags.FlattenHierarchy'는 상속 된 **'static' ** 멤버를위한 것입니다. –

+0

@JeppeStigNielsen - 감사합니다. 나는이 일을하기 위해 많은 노력을 혼란스럽게 생각합니다. –

3

는주의해야 할 두 가지가 있습니다.

(1) 당신이 사용하는 경우 :

this.GetType() 

또는 동등 단지 GetType()을, 반환되는 유형은 실제 인스턴스의 실제 런타임 유형입니다. _Default은 봉인되지 않은 클래스이므로 _Default보다 더 파생 된 (보다 특수화 된 유형) 즉 직접 또는 간접 기본 클래스로 _Default 인 일부 클래스가 될 수 있습니다. 당신이 원하는 것은 항상은 "일정"유형 _Default 경우

typeof 키워드를 사용하므로 사용

typeof(_Default) 

대신 GetType()을. 이것만으로도 문제를 해결할 수 있습니다.

(2)BindingFlags.NonPublic를 지정하더라도, private 회원이 반환되지 않습니다 상속. 선택한 바인딩 플래그를 사용하면 동일한 클래스 (파생 클래스)에 선언 된 private 메서드가 반환되지만 기본 클래스에서 상속 된 private 메서드는 반환되지 않습니다. 그러나 internalprotected 멤버의 경우 클래스 자체에서 선언 된 멤버와 기본 클래스에서 선언 된 멤버가 모두 반환됩니다.

private 메서드는 파생 클래스에서 호출 할 수 없으므로 의미가 있습니다.

DynamicHandler 방법의 액세스 수준을 private에서 예 : BindingFlags.NonPublic을 사용할 때 상속 된 보호 된 멤버가 선택되므로 protected (다른 대답에서 제안한대로)으로 문제를 해결할 수 있습니다.

BindingFlags으로 계승 된 private 회원을 얻을 수 없다는 것이 여전히 흥미 롭습니다. 관련 스레드 C#: Accessing Inherited Private Instance Members Through Reflection. 물론 모든 기본 유형을 검색하는 메소드를 작성할 수 있습니다.

static MethodInfo GetPrivateMethod(Type type, string name) 
{ 
    MethodInfo retVal; 
    do 
    { 
     retVal = type.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); 
     if (retVal != (object)null) 
      break; 
     type = type.BaseType; 
    } while (type != (object)null); 
    return retVal; 
} 

그 자체로도 문제가 해결되었을 것입니다.

6

다른 사용자를 위해서 GetMethod()은 전달한 인수가 찾으려는 메소드의 인수와 일치하지 않는 경우 null을 반환 할 수도 있습니다. 따라서, 예를 들어, 당신은 방법을 찾기 위해 노력하는 경우 :

SomeMethod(int intParam, string stringParam) 

당신은 GetMethod에 매개 변수 유형을 통과해야 : 당신이 특별한 바인딩 플래그를 지정하려는 경우,

type.GetMethod("SomeMethod", new[] { typeof(int), typeof(string) }); 

을 또는을 :

type.GetMethod("SomeMethod", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(int), typeof(string) }, null); 
+0

나는이 대답을 수십 번 발견했으며 결코 이것을 기억하지 못한다 ... – kenchilada