C# 通过反射将操作订阅到任何事件类型

C# 通过反射将操作订阅到任何事件类型,c#,.net,events,reflection,delegates,C#,.net,Events,Reflection,Delegates,考虑: someControl.Click += delegate { Foo(); }; 事件的论据是无关紧要的,我不需要它们,我对它们也不感兴趣。我只想让Foo()被调用。没有明显的方法可以通过反射实现同样的效果 我想把上面的内容翻译成 void Foo() { /* launch missiles etc */ } void Bar(object obj, EventInfo info) { Action callFoo = Foo; info.AddEventHand

考虑:

someControl.Click += delegate { Foo(); };
事件的论据是无关紧要的,我不需要它们,我对它们也不感兴趣。我只想让Foo()被调用。没有明显的方法可以通过反射实现同样的效果

我想把上面的内容翻译成

void Foo() { /* launch missiles etc */ }

void Bar(object obj, EventInfo info)
{
    Action callFoo = Foo;
    info.AddEventHandler(obj, callFoo);
}
另外,我不想假设传递给Bar的对象类型严格遵守事件使用EventHander(TArgs)签名的准则。简单地说,我正在寻找一种方法来订阅任何处理程序类型的操作;更简单的是,一种将操作委托转换为预期处理程序类型的委托的方法。

如何

static void AddEventHandler(EventInfo eventInfo, object item,  Action action)
{
  var parameters = eventInfo.EventHandlerType
    .GetMethod("Invoke")
    .GetParameters()
    .Select(parameter => Expression.Parameter(parameter.ParameterType))
    .ToArray();

  var handler = Expression.Lambda(
      eventInfo.EventHandlerType, 
      Expression.Call(Expression.Constant(action), "Invoke", Type.EmptyTypes), 
      parameters
    )
    .Compile();

  eventInfo.AddEventHandler(item, handler);
}
static void AddEventHandler(EventInfo eventInfo, object item, Action<object, EventArgs> action)
{
  var parameters = eventInfo.EventHandlerType
    .GetMethod("Invoke")
    .GetParameters()
    .Select(parameter => Expression.Parameter(parameter.ParameterType))
    .ToArray();

  var invoke = action.GetType().GetMethod("Invoke");

  var handler = Expression.Lambda(
      eventInfo.EventHandlerType,
      Expression.Call(Expression.Constant(action), invoke, parameters[0], parameters[1]),
      parameters
    )
    .Compile();

  eventInfo.AddEventHandler(item, handler);
}
void Bar(object obj, EventInfo info)
{
    var parameters = info.EventHandlerType.GetMethod("Invoke").GetParameters()
        .Select(p => Expression.Parameter(p.ParameterType));

    var handler = Expression.Lambda(
        info.EventHandlerType,
        Expression.Call(
            Expression.Constant(obj), // obj is the instance on which Foo()
            "Foo",                    // will be called
            null
        ),
        parameters
    );
    info.AddEventHandler(obj, handler.Compile());
}

如果事件中使用的委托类型具有非空返回类型,或者<代码> OUT/<代码>参数?@ Jon Skutt好点,我没有真正考虑它,您会期望发生什么?out参数和返回值对于事件来说并不是很有用。但我希望出现转换错误、异常等。基本上,为了我自己的理智,我想假设这些类型不会被用作事件处理程序。啊,令人困惑,但它是有效的!让我意识到表情的惊人(我从来没有理由使用它们)。我还没有彻底测试过这个,但我想我有我需要的。谢谢;)我找了两天:)谢谢,非常感谢:)但是我有个问题。当我将Action改为Action=(o,e)=>,它的错误。。你能帮我解决这个问题吗?@TCTarımKöyİşleri检查当前的变体
void Bar(object obj, EventInfo info)
{
    var parameters = info.EventHandlerType.GetMethod("Invoke").GetParameters()
        .Select(p => Expression.Parameter(p.ParameterType));

    var handler = Expression.Lambda(
        info.EventHandlerType,
        Expression.Call(
            Expression.Constant(obj), // obj is the instance on which Foo()
            "Foo",                    // will be called
            null
        ),
        parameters
    );
    info.AddEventHandler(obj, handler.Compile());
}