簡體   English   中英

動態事件訂閱和1個處理程序

[英]Dynamic Event Subscription and 1 handler

我已經看到了幾個答案,但不知怎的,我不能讓我的工作。 我想動態使用各種控件的任何事件(文本框,復選框,按鈕等),最好將它們分配給一個事件處理程序。 應在運行時分配處理程序。 此外,我想在處理程序中知道哪個事件觸發了處理程序。

我得到了部分工作。 使用lambda表達式我調用我的處理程序(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#將額外參數傳遞給事件處理程序?


作為替代方案,我嘗試使用表達式樹來解決問題,如下所示: 為什么在動態創建事件處理程序時會出現Argument異常? 顯然,可以從EventInfo中檢索EventHandlerType並在lambda表達式中使用它。

但是,無論我做什么,我總是得到一個InvalidOperationException“Lambda參數不在范圍內”。

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());
  }
}

我在表達樹上做錯了什么?

此外,第一段代碼看起來更干凈。 是否有可能使用第一個代碼示例得到我想要的東西?

在第二次嘗試中,變量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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM