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。现在,图书馆已经完工了,我的老板很高兴。