2012-11-19 2 views
1

Windows Phone 페이지 (MainPage)가 있고 코드 숨김에 MouseReference 이벤트에 동적으로 이벤트 처리기를 추가하려고합니다. 트릭은 내가이 이벤트 핸들러는 객체와 이벤트 인수를 갖고 싶어한다 :이벤트 처리기 인수가 메서드의 객체 인 경우 AddEventHandler

this.MouseEnter += MyEventHandler; 
:

private void MyEventHandler(object sender, object args) 
    { 

    } 

이 작동 (그 이유는이 단순화 된 예는 것입니다)

그러나이 ArgumentException이 발생합니다 :

var handlerType = Type.GetType("System.EventHandler`1"). 
        MakeGenericType(typeof(EventArgs)); 
this.GetType().GetEvent("Hold").AddEventHandler(
        this, Delegate.CreateDelegate(handlerType, this, "MyEventHandler")); 

그리고 예외의 메시지는 다음과 같습니다 "서명 또는 보안 투명성이 대리자 형식의 서명 또는 보안 투명도와 호환되지 않기 때문에 대상 메서드에 바인딩 할 수 없습니다." 이벤트 처리기의 시그니처를 변경하면 모두 작동하지만 "객체"또는 "동적"으로 유지하려고합니다.

AddEventHandler 호출과 함께 이벤트 처리기를 추가하려면 어떻게해야합니까?

도움이 매우 감사합니다.

답변

1

키워드 공분산 위임 할 수 있습니다 :

class Program 
{ 
    static void Main(string[] args) 
    { 
    var t = new Test(); 

    var e = t.GetType().GetEvent("TestEvent"); 
    var te = Delegate.CreateDelegate(e.EventHandlerType, new EventHandler(MyMethod).Method); 

    e.AddEventHandler(t, te); 

    t.RaiseTest(); 
    } 

    static void MyMethod(object sender, object args) 
    { 

    } 
} 

public class Test 
{ 
    public class MyEventArgs : EventArgs { } 

    public void RaiseTest() 
    { 
    var e = TestEvent; 
    if (e != null) 
     e(this, new MyEventArgs()); 
    } 

    public event EventHandler<MyEventArgs> TestEvent; 
} 
+1

정적이 아닌 MyMethod와 함께 작동하려면 다음과 같이하십시오. 만약 당신이 그것을 Test로 옮기고 "static"을 "public"으로 변경한다면, var te = Delegate.CreateDelegate (e.EventHandlerType, new EventHandler (MyMethod) .Method) e.EventHandlerType, t, 새 EventHandler (t.MyMethod). 메소드);'. 잠시 동안 이것을 생각하고 공유하고 싶었습니다. – ulatekh

1

EventHandler의 서명과 일치하는 메서드를 생성하려면 DynamicMethod 및 ILGenerator를 사용해야합니다. 그런 다음 DynamicMethod 구현에서 서명 void MyEventHandler (object, object)가있는 전역 이벤트 핸들러를 호출합니다.

public MainPage() 
{ 
    var handler = Create<MouseEventHandler>(); 
    this.LayoutRoot.MouseMove += handler; 
} 

public static void MyEventHandler(object sender, object args) 
{ 
    Debug.WriteLine("MyEventHandler({0}, {1})", sender, args); 
} 

private TDelegate Create<TDelegate>() 
{ 
    // retrieve parameter types from delegate type 
    var delegateType = typeof(TDelegate); 
    var invoke = delegateType.GetMethod("Invoke"); 
    var parameterTypes = (from p in invoke.GetParameters() 
          select p.ParameterType).ToArray(); 

    // create dynamic event handler having TDelegate signature 
    var method = new DynamicMethod("", null, parameterTypes); 
    var myEventHandlerMethod = typeof(MainPage).GetMethod("MyEventHandler"); 

    var generator = method.GetILGenerator(); 
    generator.Emit(OpCodes.Ldarg_0); 
    generator.Emit(OpCodes.Ldarg_1); 
    generator.Emit(OpCodes.Call, myEventHandlerMethod); // invoke my event handler 
    generator.Emit(OpCodes.Ret); 

    return (TDelegate)(object)method.CreateDelegate(delegateType); 
} 
0
는 트릭해야 배치

익명있어서 this.MouseEnter + = (S, E) =>이 MyEventAPIHandler (S, e)를;

+0

죄송합니다,이 작동하지 않습니다 - 난 반사를 사용해야하는 이유는 이벤트 속성에 액세스 할 수없는, 즉이다. 또한 리플렉션을 사용하여 이벤트의 인수 유형에 액세스 할 수 있습니다. 위의 this.MouseEnter를 사용하는 이유는 반향을 통해 달성하고 싶은 것을 설명하는 것이므로 다른 방법으로는 수행 할 수 없기 때문입니다. –