You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# 使用反射动态订阅泛型EventHandler事件时报指定转换无效错误求助

问题根因

出现Specified cast is not valid异常有两个核心原因:

  1. 委托类型不匹配:你定义的事件是泛型委托EventHandler<PowerStateEventsArgs>,但绑定事件时你用的是非泛型的EventHandler,两者类型不兼容,所以抛出转换失败异常。
  2. AddEventHandler参数传值错误:你的事件是静态事件,该方法第一个参数对于静态事件应传入null,对于实例事件才需要传入类的实例对象,你之前传入d._projectors.fullClass(Type类型对象)属于参数错误。
可行解决方案

方案1:已知事件参数类型直接绑定

适合事件数量少、参数类型已知的场景,代码如下:

foreach(var evnt in d._projectors._events)
{
    EventInfo ev = evnt.Value;
    try
    {
        if (evnt.Key == "OnPowerStateRecieved")
        {
            // 静态事件第一个参数传null,委托使用对应泛型类型
            ev.AddEventHandler(null, new EventHandler<PowerStateEventsArgs>(DisplayChangeEvents.DisplayPowerChangedEvent));
        }
        else if (evnt.Key == "OnMuteStateRecieved")
        {
            // 按实际的静音事件参数类型替换MuteStateEventsArgs
            ev.AddEventHandler(null, new EventHandler<MuteStateEventsArgs>(DisplayChangeEvents.DisplayMuteChangedEvent));
        }
    }
    catch (Exception ex)
    {
        ErrorLog.Error("Error creating event handlers :  " +  ex.Message + "\r");
    }
}

注意对应处理方法的签名必须和委托匹配,比如DisplayPowerChangedEvent的签名应为:

public static void DisplayPowerChangedEvent(object sender, PowerStateEventsArgs e)
{
    // 你的处理逻辑
}

方案2:动态创建委托实现通用绑定

适合事件数量多、需要统一处理绑定逻辑的场景,不需要手动指定泛型参数:

foreach(var evnt in d._projectors._events)
{
    EventInfo ev = evnt.Value;
    try
    {
        Type delegateType = ev.EventHandlerType;
        MethodInfo handleMethod = null;
        
        // 匹配事件对应的处理方法
        switch(evnt.Key)
        {
            case "OnPowerStateRecieved":
                handleMethod = typeof(DisplayChangeEvents).GetMethod(nameof(DisplayChangeEvents.DisplayPowerChangedEvent));
                break;
            case "OnMuteStateRecieved":
                handleMethod = typeof(DisplayChangeEvents).GetMethod(nameof(DisplayChangeEvents.DisplayMuteChangedEvent));
                break;
        }
        
        if(handleMethod != null)
        {
            Delegate handler = Delegate.CreateDelegate(delegateType, handleMethod);
            // 静态事件传null,实例事件替换为你实际使用的类实例对象
            ev.AddEventHandler(null, handler);
        }
    }
    catch (Exception ex)
    {
        ErrorLog.Error("Error creating event handlers :  " +  ex.Message + "\r");
    }
}

额外注意事项

  • 如果你后续改为使用实例事件而非静态事件,AddEventHandler第一个参数必须传入你程序中实际用来调用类方法的那个实例,不能每次临时Activator.CreateInstance创建新实例,否则新实例的事件触发和你正在使用的实例无关,无法收到事件通知。
  • 如果你自己修改了事件的访问器逻辑,要确保自定义的add访问器没有做额外的类型校验,避免合法委托被拦截。

内容的提问来源于stack exchange,提问作者cmac_t0ld

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 19:15:01