2013-03-15 78 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