1

Windows Phoneページ(MainPage)があり、コードビハインドで、イベントハンドラーを動的に追加します(たとえば、MouseEnterイベント)。秘訣は、このイベントハンドラーにイベント引数をオブジェクトとして持たせたいということです。

    private void MyEventHandler(object sender, object args)
    {

    }

(この理由は、これが単純化された例であるためです)

これは機能します:

this.MouseEnter += MyEventHandler;

しかし、これはArgumentExceptionをスローします。

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

また、例外のメッセージは次のとおりです。「ターゲットメソッドの署名またはセキュリティの透過性がデリゲートタイプのものと互換性がないため、ターゲットメソッドにバインドできません。」イベントハンドラーの署名を変更すると、すべて機能しますが、「オブジェクト」または「動的」として保持したいと思います。

AddEventHandler呼び出しでイベントハンドラーを追加するにはどうすればよいですか?

どんな助けでも大歓迎です。

4

3 に答える 3

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;
}
于 2012-11-19T19:55:32.133 に答える
1

イベントハンドラのシグネチャに一致するメソッドを生成するには、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);
}
于 2012-11-19T14:09:43.630 に答える
0

それをラップする匿名メソッドはトリックを実行する必要があります:this.MouseEnter + =(s、e)=> MyEventHandler(s、e);

于 2012-11-19T15:42:11.990 に答える