2013-03-15 73 views
3

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

我得到這個部分工作。使用lambda表達式我調用我的處理程序(EventAssistant)並傳遞一個包含事件名稱的額外參數(command)。它適用於使用類型EventHandler的事件。但是,它不適用於期望使用不同處理程序的事件,如類型爲MouseEventHandler的事件。它將無法在AddEventHandler中訂閱。基於C# passing extra parameters to an event handler?


正如我試圖解決與表達式樹中的問題的另

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 
} 

如下所示:Why am I getting an Argument exception when creating event handler dynamically? 顯然,EventHandlerType可以從EventInfo被檢索,並在使用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()); 
    } 
} 

我在做什麼錯了表達式樹?

此外,第一段代碼看起來更乾淨。使用第一個代碼示例可以獲得我想要的內容嗎?

+0

看看Skeets回答[這裏](http://stackoverflow.com/questions/1574427/lambda-parameter-not-in-scope-while-building-binary-lambda-expression)我認爲你有同樣的問題你的表達樹。 – Amicable 2013-03-15 16:10:36

+0

我編輯了你的標題。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 – 2013-03-15 16:41:58

回答

1

在你的第二次嘗試,變量c不應該是一個​​,但設置爲當前command,而不是價值ConstantExpression。在當前的代碼,你正在創建一個處理程序,它本質上是這樣的:

(_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) 
+0

這個伎倆!當然,EventAssistant還不夠通用,無法接受所有類型的事件處理程序,但我會將其保存爲後續問題。 – 2013-03-16 12:18:07