Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何正确序列化.net 4.7、[x]+;中的异常;,和.net标准2.[x]&x2B;_C#_Exception_Serialization_Iserializable - Fatal编程技术网

C# 如何正确序列化.net 4.7、[x]+;中的异常;,和.net标准2.[x]&x2B;

C# 如何正确序列化.net 4.7、[x]+;中的异常;,和.net标准2.[x]&x2B;,c#,exception,serialization,iserializable,C#,Exception,Serialization,Iserializable,我有一些Exception派生类型,它们向Exception添加了额外的属性。在web上搜索有关如何处理此类基于异常的类型的序列化的示例和指导原则会导致描述和代码示例非常陈旧。尝试这些示例总是会导致安全错误。 为了使其正常工作,我必须用System.Security.SecurityCritical属性另外修饰GetObjectData-方法 有趣的是,SecurityPermission-属性似乎不是必需的,它包含在所有示例中,但以各种方式存在。有些示例仅将其添加到GetObjectData,

我有一些
Exception
派生类型,它们向
Exception
添加了额外的属性。在web上搜索有关如何处理此类基于
异常的类型的序列化的示例和指导原则会导致描述和代码示例非常陈旧。尝试这些示例总是会导致安全错误。
为了使其正常工作,我必须用
System.Security.SecurityCritical
属性另外修饰
GetObjectData
-方法

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

我的问题是,下面的
异常
派生类型(对于它的序列化部分)是否适用于现在的.net框架(4.7.[x]+,Core[x],Standard2.[x]+),或者是否缺少某些内容,或者我甚至可以删除某些部分?请注意,我不想密封类型。其他
异常
-类型应该能够从中派生

[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;
}
派生类型(
fooberException
)还必须在反序列化构造函数上设置
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;


}
来源


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

[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
(取决于具体情况,例如上述情况)。

如果需要在.NETCore中工作,则没有必要创建异常[Serializable]。不支持远程处理和appdomains。您使用的序列化程序是什么<代码>二进制格式化程序
?或者其他东西,比如Json.NET?还有,你看到了吗?@dbc:没有特定的格式化程序。我正在完成一些库,FX cop一直在唠叨关于GetObjectData覆盖的问题。这引起了我对如何正确处理这一问题的兴趣。就我所见,我的实现(见我的帖子)应该可以与实际的框架相匹配。正如MS在基类上所做的那样,我在GetObjectData上使用SecurityCritical-不需要部分信任或不受信任的代码来访问此方法。它实际上只用于序列化目的。如果正确理解Hans Passant,序列化功能的重要性正在逐渐消失,因为.net Core不支持它。您也可以使用中所示的
ISafeSerializationData
模式,但并非所有序列化程序都支持该模式。具体而言,您需要做一些技巧才能让它与Json.NET一起工作,请参见和。我认为这样可以。fxcop不再抱怨了,我有单元测试,可以很好地工作。不需要扩展复杂性。但是谢谢,也许有一天我会使用ISafeSerializationData。现在,图书馆已经完工了,我的老板很高兴。