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

请教Action订阅方法源码查看及跨AppDomain事件订阅报错问题

解答

用户代码示例:

public class Test{
    void Method(){
        var testDomain=AppDomain.CreateDomain("TestDomain");
        var targetClass= (TargetClass)testDomain.CreateInstanceFromAndUnwrap("SomeDll","ClassName");  
        targetClass.changeEvent+= localMethod;// 此处抛出Test类无Serializable特性的异常
    }
    public void localMethod(){
        // do something
    }
}
public class TargetClass{
    public event Action changeEvent;
}

关于Test类需要Serializable特性的原因

跨AppDomain场景下订阅事件时,CLR会创建绑定到localMethod的委托实例,这个委托需要从当前AppDomain传递到你创建的TestDomain中。由于localMethod是Test类的实例方法,委托内部会持有Test类的实例引用——而.NET的跨AppDomain对象传递机制要求对象必须可序列化,因此Test类必须标记[Serializable]特性,否则序列化委托时会抛出异常。

两种替代方案(无需给Test加Serializable)

  • 将localMethod改为静态方法:静态方法的委托不需要持有类实例引用,跨域时无需序列化Test类
  • 让Test类继承MarshalByRefObject:此时对象会以“按引用封送”的方式跨AppDomain传递,而非序列化拷贝

关于查看Action订阅方法的源码

Action是.NET内置的泛型委托类型,其订阅逻辑(+=操作)依赖委托的组合机制,可通过以下方式查看源码:

  • 使用dnSpy时,加载对应的核心程序集:.NET Framework下是mscorlib.dll,.NET Core/.NET 5+下是System.Runtime.dll,定位到System命名空间下的Action(包括无参和泛型版本),其Combine静态方法就是委托组合(订阅事件的核心逻辑);事件默认的add访问器会调用该方法合并原有委托与新委托
  • 若dnSpy未找到,检查是否加载了正确的核心程序集,这类基础类型均存在于.NET核心库中
  • 也可查看.NET官方开源仓库的核心库源码,委托的组合逻辑、事件默认访问器的实现都有清晰的代码定义

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:25:29