我有一些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
声明(取决于情况,例如对于上述情况(。