3

私はすでにいくつかの答えを見てきましたが、どういうわけか私は私の仕事をさせることができません。さまざまなコントロール(テキストボックス、チェックボックス、ボタンなど)のイベントを動的に使用し、できればそれらを1つのイベントハンドラーに割り当てたいと思います。ハンドラーは実行時に割り当てる必要があります。さらに、どのイベントがハンドラーをトリガーしたかをハンドラーで知りたいです。

これを部分的に機能させました。ラムダ式を使用して、ハンドラー(EventAssistant)を呼び出し、イベントの名前を含む追加のパラメーター(コマンド)を渡します。これは、タイプEventHandlerを使用するイベントに対して機能します。ただし、MouseEventHandlerタイプなどの別のハンドラーを予期するイベントでは機能しません。AddEventHandlerでのサブスクライブに失敗します。

private void RegisterEventHandlers(Control ctl)
{
  foreach (Command command in CommandList)
  {
    EventInfo eventInfo = ctl.GetType().GetEvent(command.Name);
    EventHandler handler = (sender, args) =>
    {
      EventAssistant(sender, args, command);
    };
    eventInfo.AddEventHandler(ctl, handler);
  }
}

public void EventAssistant(object sender, EventArgs e, Command c)
{
  //do lots of other fun stuff
}

イベントハンドラーに追加のパラメーターを渡すC#に基づいていますか?


別の方法として、次のように式ツリーの問題を解決しようとしました。イベントハンドラーを動的に作成するときに引数例外が発生するのはなぜですか。 どうやら、EventHandlerTypeはEventInfoから取得して、ラムダ式で使用できます。

しかし、私が何をしても、常にInvalidOperationException「スコープ内にないラムダパラメーター」が発生します。

private void RegisterEventHandlers(Control ctl)
{
  foreach (Command command in CommandList)
  {
    EventInfo eventInfo = ctl.GetType().GetEvent(command.Name);

    var sender = Expression.Parameter(typeof(object), "sender");
    var e = Expression.Parameter(typeof(EventArgs), "e");
    var c = Expression.Parameter(typeof(Command), "command");
    Expression[] arg = new Expression[] { sender, e, c };
    MethodInfo mi = this.GetType().GetMethod("EventAssistant");
    var body = Expression.Call(Expression.Constant(this), mi, arg);
    var lambda = Expression.Lambda(eventInfo.EventHandlerType, body, sender, e);

    eventInfo.AddEventHandler(ctl, lambda.Compile());
  }
}

式ツリーで何が問題になっていますか?

また、コードの最初の部分ははるかにきれいに見えます。最初のコードサンプルを使用して、必要なものを取得することはできますか?

4

1 に答える 1

1

2 回目の試行では、変数cはではなくParameterExpression、代わりConstantExpressionに現在の値に設定された になりcommandます。現在のコードでは、基本的に次のようなハンドラーを作成しています。

(_sender, _e) => this.EventAssistant(_sender, _e, _c)
// The expression expects "_c" to be a parameter of the lambda, which is why
// you're getting that exception

ただし、変更する場合は

var c = Expression.Parameter(typeof(Command), "command");

var c = Expression.Constant(command);

生成されたコードは期待どおりに見えます (そしてもちろん動作します):

(_sender, _e) => this.EventAssistant(_sender, _e, command)
于 2013-03-15T16:44:58.993 に答える