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

如何通过反射订阅外部类的内部静态Action事件?

订阅/移除内部静态Action事件的方案

因为目标事件是internal访问修饰符的静态事件,且无法修改定义它的类,只能通过反射绕过访问限制完成委托的订阅与移除。以下是具体实现步骤和代码示例:

核心思路

自动实现的event在编译后会生成对应私有静态字段(字段名格式为<事件名>k__BackingField),我们可以通过反射获取该字段,直接操作字段值来添加或移除委托。

添加委托的代码示例

using System;
using System.Reflection;

// 假设外部类名为ExternalSingletonClass
Type targetType = typeof(ExternalSingletonClass);
// 获取事件对应的后台字段
FieldInfo eventField = targetType.GetField("<OnSingletonReady>k__BackingField", 
    BindingFlags.Static | BindingFlags.NonPublic);

if (eventField != null)
{
    // 定义要订阅的委托逻辑
    Action myHandler = () => 
    {
        Console.WriteLine("Singleton ready event triggered");
    };

    // 获取当前事件的委托实例
    Action currentDelegate = (Action)eventField.GetValue(null);
    // 合并新委托与现有委托
    Action newDelegate = (Action)Delegate.Combine(currentDelegate, myHandler);
    // 将合并后的委托赋值回字段
    eventField.SetValue(null, newDelegate);
}

移除委托的代码示例

using System;
using System.Reflection;

Type targetType = typeof(ExternalSingletonClass);
FieldInfo eventField = targetType.GetField("<OnSingletonReady>k__BackingField", 
    BindingFlags.Static | BindingFlags.NonPublic);

if (eventField != null)
{
    // 注意:必须引用之前订阅时的同一个委托实例
    Action myHandler = // 此处关联订阅时保存的委托对象

    Action currentDelegate = (Action)eventField.GetValue(null);
    // 从现有委托中移除目标委托
    Action newDelegate = (Action)Delegate.Remove(currentDelegate, myHandler);
    eventField.SetValue(null, newDelegate);
}

注意事项

  • 字段名兼容性:自动实现事件的后台字段名格式<事件名>k__BackingField是C#编译器的标准生成规则,但如果目标事件是手动实现的(而非自动属性式定义),则需要找到对应的实际字段名。
  • 委托实例一致性:移除委托时必须使用和订阅时完全相同的委托实例,否则Delegate.Remove无法生效,建议将订阅的委托对象保存为类成员变量方便后续操作。
  • 反射权限:确保程序运行时有足够权限访问私有成员,普通应用场景下无需额外配置,但沙箱或严格权限控制场景可能受限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 18:18:16