1

作为我的问题的后续,我正在尝试创建一个匿名事件处理程序,其参数是在运行时决定的。

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

    List<ParameterExpression> callArguments = new List<ParameterExpression>();
    foreach (ParameterInfo parameter in eventInfo.EventHandlerType.GetMethod("Invoke").GetParameters())
    {
      callArguments.Add(Expression.Parameter(parameter.ParameterType, parameter.Name));
    }

    //begin pseudo code
    method = (callArguments) => 
    {
      if (sender != null) ...
      if (e != null) ...
      name = command.name;
    };
    or
    method = new delegate
    {
      if (sender != null) ...
      if (e != null) ...
      name = command.name;
    };
    //end pseudo code

    var body = Expression.Call(Expression.Constant(this), method, callArguments);
    var lambda = Expression.Lambda(eventInfo.EventHandlerType, body, callArguments);

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

我发现我对 lambda 表达式和委托的知识太缺乏解决这个问题......

匿名处理程序只需将发送者对象、事件参数和命令对象转发给另一个函数。并非所有事件都具有相同的参数,因此我想到将处理程序定义为具有动态参数的匿名函数。

但是,非常欢迎其他可能解决我的问题的解决方案。

4

1 回答 1

0

您可以将委托/lambda 声明为采用 params 数组:

method = delegate(params object[] args)
{
    ...
};

在其中,使用 MethodInfo 类获取有关应将参数转发到的方法的信息。

但我认为你在这里太有活力了。反射允许您绕过使用编译时功能时所需的正常抽象机制。这会导致复杂性、可读性丧失,并将大量编译时错误转化为运行时错误。您仍然可以在运行时使用多态性和委托来决定内容,同时保持可读性和编译时类型安全。微软在他们的库中都这样做了。除了在 System.Reflection 命名空间的实际实现中,您永远不会看到需要使用反射的库。

于 2013-03-18T13:46:20.513 回答