0

我有一些Exception派生类型,它们为Exception. 在网上搜索有关如何处理此类Exception基于类型的序列化的示例和指南导致描述和代码示例相当陈旧。尝试这些样本总是会导致安全错误。为了使它工作,我必须额外用属性装饰GetObjectData-Method 。System.Security.SecurityCritical

有趣的SecurityPermission是,所有示例中都包含但以各种方式包含的 -Attribute 似乎不是必需的。有些示例仅将其添加到 . GetObjectData,有些示例还将其添加到反序列化构造函数中。一些示例使用了强大的SecurityAction.Demand-action,大多数示例使用了SecurityAction.LinkDemand-action 和其他声明的SecurityAction.RequestMinimum

我的问题是,以下Exception派生类型(对于它的序列化部分)是否适合与当今的 .net 框架(4.7.[x]+、Core[x]、Standard2.[x]+)一起使用,或者如果有什么东西不见了,或者我什至可以删除一些零件?请注意,我不想密封类型。其他Exception类型应该能够从中派生。

[Serializable]
public class FooException : Exception{

    readonly int m_fooValue;

    public FooException(string message,int fooValue,Exception innerException=null) : base(message,innerException){
        m_fooValue = fooValue;
    }
    [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
    protected FooException(SerializationInfo info, StreamingContext context) : base(info, context) {
        m_fooValue = info.GetInt32(nameof(FooValue));            
    }

    [SecurityCritical]
    [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
    public override void GetObjectData(SerializationInfo info, StreamingContext context) {
        if (info == null) throw new ArgumentNullException(nameof(info));
        info.AddValue(nameof(FooValue), m_fooValue);            
        base.GetObjectData(info, context);
    }

    public int FooValue => m_fooValue;
}

派生类型 ( FooBarException) 还必须SecurityCritical在反序列化构造函数上设置 - 属性以满足LinkDemand

[Serializable] 
public class FooBarException : FooException{

    readonly int m_barValue;

    public FooBarException(string message,int fooValue, int barValue, Exception innerException = null) : base(message, fooValue, innerException) {
        m_barValue = barValue;
    }
    [SecurityCritical] // Additional for satisfying the LinkDemand on the base constructor
    [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
    protected FooBarException(SerializationInfo info, StreamingContext context) : base(info, context) {
        m_barValue = info.GetInt32(nameof(BarValue));
    }

    [SecurityCritical]
    [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
    public override void GetObjectData(SerializationInfo info, StreamingContext context) {
        if (info == null) throw new ArgumentNullException(nameof(info));
        info.AddValue(nameof(BarValue), m_barValue);
        base.GetObjectData(info, context);
    }

    public int BarValue => m_barValue;


}

来源
https://stackoverflow.com/a/100369/340628

https://docs.microsoft.com/en-us/dotnet/api/system.runtime.serialization.iserializable.getobjectdata?view=netframework-4.8

使自定义 .NET 异常可序列化的正确方法是什么?

https://blog.gurock.com/articles/creating-custom-exceptions-in-dotnet/

4

1 回答 1

1

在深入挖掘之后,我得出了以下模式:

[Serializable]
public class FooException : Exception{

    readonly int m_fooValue;

    public FooException(string message, int fooValue, Exception innerException = null) : base(message, innerException) {
        m_fooValue = fooValue;
    }

    [SecuritySafeCritical]
    protected FooException(SerializationInfo info, StreamingContext context) : base(info, context) {
        m_fooValue = info.GetInt32(nameof(FooValue));
    }

    [SecurityCritical]      
    public override void GetObjectData(SerializationInfo info, StreamingContext context) {
        if (info == null) throw new ArgumentNullException(nameof(info));
        info.AddValue(nameof(FooValue), m_fooValue);
        base.GetObjectData(info, context);
    }

    public int FooValue => m_fooValue;
}

[Serializable]
public class FooBarException : FooException
{

    readonly int m_barValue;

    public FooBarException(string message, int fooValue, int barValue, Exception innerException = null) : base(message, fooValue, innerException) {
        m_barValue = barValue;
    }
    [SecuritySafeCritical]        
    protected FooBarException(SerializationInfo info, StreamingContext context) : base(info, context) {
        m_barValue = info.GetInt32(nameof(BarValue));
    }

    [SecurityCritical]        
    public override void GetObjectData(SerializationInfo info, StreamingContext context) {
        if (info == null) throw new ArgumentNullException(nameof(info));
        info.AddValue(nameof(BarValue), m_barValue);
        base.GetObjectData(info, context);
    }

    public int BarValue => m_barValue;


}

对于SecurityAction.LinkDemand问题的 - 部分,不应再使用此值(.net 4+)。要么SecurityAction.Demand将被使用,甚至整个SecurityPermission声明都可以替换为SecurityCritical(取决于情况,例如上述情况)。

于 2020-02-20T17:22:22.377 回答