如何在 .net 4.7.[x]+ 和 .net Standard 2.[x]+ 中正确序列化异常
How to correctly serialize Exceptions in .net 4.7.[x]+, and .net Standard 2.[x]+
我有一些 Exception
派生类型,它们为 Exception
添加了额外的属性。在网络上搜索有关如何处理此类基于 Exception
的类型的序列化的示例和指南会导致相当陈旧的描述和代码示例。尝试这些样本总是会导致安全错误。
为了让它工作,我不得不用 System.Security.SecurityCritical
属性额外装饰 GetObjectData
-Method。
有趣的是,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;
}
来源
What is the correct way to make a custom .NET Exception serializable?
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
,要么甚至整个 SecurityPermission
声明都可以替换为 SecurityCritical
(视情况而定,例如上述情况)。
我有一些 Exception
派生类型,它们为 Exception
添加了额外的属性。在网络上搜索有关如何处理此类基于 Exception
的类型的序列化的示例和指南会导致相当陈旧的描述和代码示例。尝试这些样本总是会导致安全错误。
为了让它工作,我不得不用 System.Security.SecurityCritical
属性额外装饰 GetObjectData
-Method。
有趣的是,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;
}
来源
What is the correct way to make a custom .NET Exception serializable?
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
,要么甚至整个 SecurityPermission
声明都可以替换为 SecurityCritical
(视情况而定,例如上述情况)。