如何正确序列化.net 4.7.[x]+和.net Standard 2.[x]+中的Exceptions



我有一些Exception派生类型,它们为Exception添加了额外的属性。在网络上搜索关于如何处理这种基于Exception的类型的序列化的示例和指南,得到了相当古老的描述和代码示例。尝试这些示例总是会导致安全错误。为了使它发挥作用,我不得不用System.Security.SecurityCritical属性对GetObjectData-方法进行额外的修饰。

有趣的是,SecurityPermission-属性似乎没有必要,它包含在所有的示例中,但以各种方式存在。有些示例仅将其添加到GetObjectData,有些示例还将其添加至反序列化构造函数。一些示例使用强SecurityAction.Demand-操作,大多数示例使用SecurityAction.LinkDemand-操作,其他示例声明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://learn.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/

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

[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,要么甚至可以用SecurityCritical替换整个SecurityPermission声明(取决于情况,例如对于上述情况(。

相关内容

  • 没有找到相关文章

最新更新