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

如何在.NET 4+中实现ISerializable且不违反继承安全规则?

解决.NET 4.5中结构体实现ISerializable在沙箱环境的安全异常问题

我来帮你拆解这个问题——这本质上是.NET 4.0开始的安全规则变更(Level2安全规则)和部分信任沙箱环境交互导致的权限匹配问题,咱们一步步解决:

问题根源

在.NET 3.5(Noda Time 1.x的目标框架)中,CLR使用Level1安全规则,对显式接口实现的安全权限检查比较宽松。但.NET 4.0+默认启用了Level2安全规则,要求实现接口方法的安全可访问性必须和原接口方法完全一致。

具体到你的场景:ISerializable.GetObjectData方法在.NET 4+中是被标记为[SecurityCritical]的,而你的结构体在.NET Fiddle这类沙箱(部分信任环境)中运行时,未正确标记的显式实现方法触发了"继承安全规则违反"的TypeLoadException。

正确的解决方案组合

要让可序列化结构体在.NET 4.5+的沙箱环境中正常工作,需要同时满足以下两个条件:

1. 为程序集添加AllowPartiallyTrustedCallers属性

这是沙箱环境运行的基础,告诉CLR该程序集允许被部分信任的代码调用,添加到你的类库项目的AssemblyInfo.cs或者命名空间上方:

[assembly: AllowPartiallyTrustedCallers]

2. 对显式实现的GetObjectData方法标记[SecurityCritical]

因为ISerializable.GetObjectData本身是SecurityCritical级别的,你的实现必须严格匹配这个安全级别。注意要把标记直接加在显式实现的方法上,即使是结构体:

[Serializable]
public struct CustomStruct : ISerializable
{
    private CustomStruct(SerializationInfo info, StreamingContext context)
    { }

    [SecurityCritical]
    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
    {
        // 这里实现你的序列化逻辑
        throw new NotImplementedException();
    }
}

为什么不推荐回退到Level1规则?

你提到的添加[assembly: SecurityRules(SecurityRuleSet.Level1)]虽然能临时解决问题,但会让程序集回到旧的安全模型,不仅可能引入潜在安全风险,还不符合.NET 4+的设计意图,所以不建议作为长期方案。

为什么之前的尝试没生效?

  • 单独添加SecurityPermission:这只是声明方法需要的权限,但没有匹配接口方法的安全级别标记,Level2规则下仍然不满足权限一致性要求。
  • 单独添加SecuritySafeCritical:这个标记用于允许部分信任代码调用关键方法,但接口方法本身是SecurityCritical,所以实现必须也是SecurityCritical,SafeCritical的级别不匹配。
  • 未添加AllowPartiallyTrustedCallers:即使标记了SecurityCritical,部分信任的沙箱代码也无法调用你的程序集,必须有这个属性放行。

验证修改

按照上述调整后,你的测试项目应该能正常运行:

  • 确保UntrustedCode程序集同时添加[assembly: AllowPartiallyTrustedCallers]和结构体GetObjectData方法的[SecurityCritical]标记
  • 不需要修改CodeRunner项目的代码
  • 运行后不会再抛出TypeLoadException

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:49:05