SYSLIB0051:旧序列化支持 API 已过时
从 .NET 8 开始,以下类型的 API 已过时。 在代码中调用这些方法会在编译时生成警告 SYSLIB0051
。
- 遵循模式
.ctor(SerializationInfo, StreamingContext)
的所有公共或受保护的序列化构造函数。 此类构造函数的一个示例是 Exception(SerializationInfo, StreamingContext)。 - ISerializable.GetObjectData(SerializationInfo, StreamingContext) 方法的所有隐式实现,例如 System.Exception.GetObjectData(SerializationInfo, StreamingContext)。
- IObjectReference.GetRealObject(StreamingContext) 方法的所有隐式实现,例如 System.Reflection.ParameterInfo.GetRealObject(StreamingContext)。
有关受影响的 API 的完整列表,请参阅过时的 API - SYSLIB0051。
解决方法
如果创建了派生自 System.Exception 的自定义类型,请考虑是否确实需要对其进行可序列化。 你可能不需要对其进行可序列化,因为异常序列化的主要目的是支持远程处理,并且 .NET Core 1.0 中已删除对远程处理的支持。
如果自定义异常类型的定义类似于以下代码片段所示内容,则只需移除
[Serializable]
属性、序列化构造函数和 GetObjectData(SerializationInfo, StreamingContext) 方法重写。[Serializable] // Remove this attribute. public class MyException : Exception { public MyException() { } public MyException(string message) : base(message) { } public MyException(string message, Exception inner) : base(message, inner) { } // Remove this constructor. protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { // ... } // Remove this method. public override void GetObjectData(SerializationInfo info, StreamingContext context) { // ... base.GetObjectData(info, context); } }
在某些情况下,你可能无法从自定义异常类型中移除这些 API,例如,在生成受 API 兼容性要求限制的库时。 在这种情况下,建议使用
SYSLIB0051
诊断代码使你自己的序列化构造函数和GetObjectData
方法过时,如以下代码所示。 由于理想情况下,位于序列化基础结构本身之外的任何人都不应调用这些 API,因此过时应仅影响创建自定义异常类型的子类的其他类型。 它不应对捕获、构造或使用自定义异常类型的任何人产生极为迅速和广泛的影响。[Serializable] public class MyException : Exception { public MyException() { } public MyException(string message) : base(message) { } public MyException(string message, Exception inner) : base(message, inner) { } [Obsolete(DiagnosticId = "SYSLIB0051")] // Add this attribute to the serialization ctor. protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { // ... } [Obsolete(DiagnosticId = "SYSLIB0051")] // Add this attribute to GetObjectData. public override void GetObjectData(SerializationInfo info, StreamingContext context) { // ... base.GetObjectData(info, context); } }
如果以 .NET Framework 和 .NET 8+ 作为交叉目标,则可以使用
#if
语句有条件地应用过时。 这是 .NET 团队在交叉设定运行时目标时在 .NET 库代码库中使用的相同策略。[Serializable] public class MyException : Exception { // ... #if NET8_0_OR_GREATER [Obsolete(DiagnosticId = "SYSLIB0051")] // add this attribute to the serialization ctor #endif protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { // ... } #if NET8_0_OR_GREATER [Obsolete(DiagnosticId = "SYSLIB0051")] // add this attribute to GetObjectData #endif public override void GetObjectData(SerializationInfo info, StreamingContext context) { // ... base.GetObjectData(info, context); } }
如果你已声明一种类型,该类型可创建具有
[Serializable]
属性的 .NET 类型的子类,并且你收到SYSLIB0051
警告,请按照上一项目符号点中关于自定义异常类型的指导进行操作。
提示
如果 [Serializable]
自定义类型不创建 .NET 类型的子类,则不会显示 SYSLIB0051
警告。 但是,不建议以这种方式对类型进行批注,因为像 System.Text.Json
这样的新式序列化库不需要它们。 请考虑移除 [Serializable]
属性和 ISerializable
接口。 依靠序列化库通过其公共属性(而不是专用字段)来访问类型的对象。
抑制警告
如果必须使用已过时的 API,可在代码或项目文件中禁止显示警告。
若只想抑制单个冲突,请将预处理器指令添加到源文件以禁用该规则,然后重新启用警告。
// Disable the warning.
#pragma warning disable SYSLIB0051
// Code that uses obsolete API.
// ...
// Re-enable the warning.
#pragma warning restore SYSLIB0051
若要禁止显示项目中的所有 SYSLIB0051
警告,请将属性 <NoWarn>
添加到项目文件。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<NoWarn>$(NoWarn);SYSLIB0051</NoWarn>
</PropertyGroup>
</Project>
有关详细信息,请参阅取消警告。