Call base class methods on ISerializable types
TypeName |
CallBaseClassMethodsOnISerializableTypes |
CheckId |
CA2236 |
Category |
Microsoft.Usage |
Breaking Change |
NonBreaking |
Cause
An externally visible type derives from a type that implements the System.Runtime.Serialization.ISerializable interface, and one of the following conditions is true:
The type implements the serialization constructor, that is, a constructor with the System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext parameter signature, but does not call the serialization constructor of the base type.
The type implements the System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext) method but does not call the GetObjectData method of the base type.
Rule Description
In a custom serialization process, a type implements the GetObjectData method to serialize its fields and the serialization constructor to de-serialize the fields. If the type derives from a type that implements the ISerializable interface, the base type GetObjectData method and serialization constructor should be called to serialize/de-serialize the fields of the base type. Otherwise, the type will not be serialized and de-serialized correctly. Note that if the derived type does not add any new fields, the type does not need to implement the GetObjectData method nor the serialization constructor or call the base type equivalents.
How to Fix Violations
To fix a violation of this rule, call the base type GetObjectData method or serialization constructor from the corresponding derived type method or constructor.
When to Exclude Warnings
Do not exclude a warning from this rule.
Example
The following example shows a derived type that satisfies the rule by calling the serialization constructor and GetObjectData method of the base class.
Imports System
Imports System.Runtime.Serialization
Imports System.Security.Permissions
Namespace UsageLibrary
<SerializableAttribute> _
Public Class BaseType
Implements ISerializable
Dim baseValue As Integer
Sub New()
baseValue = 3
End Sub
Protected Sub New( _
info As SerializationInfo, context As StreamingContext)
baseValue = info.GetInt32("baseValue")
End Sub
<SecurityPermissionAttribute(SecurityAction.Demand, _
SerializationFormatter := True)> _
Overridable Sub GetObjectData( _
info As SerializationInfo, context As StreamingContext) _
Implements ISerializable.GetObjectData
info.AddValue("baseValue", baseValue)
End Sub
End Class
<SerializableAttribute> _
Public Class DerivedType: Inherits BaseType
Dim derivedValue As Integer
Sub New()
derivedValue = 4
End Sub
Protected Sub New( _
info As SerializationInfo, context As StreamingContext)
MyBase.New(info, context)
derivedValue = info.GetInt32("derivedValue")
End Sub
<SecurityPermissionAttribute(SecurityAction.Demand, _
SerializationFormatter := True)> _
Overrides Sub GetObjectData( _
info As SerializationInfo, context As StreamingContext)
info.AddValue("derivedValue", derivedValue)
MyBase.GetObjectData(info, context)
End Sub
End Class
End Namespace
using System;
using System.Runtime.Serialization;
using System.Security.Permissions;
namespace UsageLibrary
{
[SerializableAttribute]
public class BaseType : ISerializable
{
int baseValue;
public BaseType()
{
baseValue = 3;
}
protected BaseType(
SerializationInfo info, StreamingContext context)
{
baseValue = info.GetInt32("baseValue");
}
[SecurityPermissionAttribute(SecurityAction.Demand,
SerializationFormatter = true)]
public virtual void GetObjectData(
SerializationInfo info, StreamingContext context)
{
info.AddValue("baseValue", baseValue);
}
}
[SerializableAttribute]
public class DerivedType : BaseType
{
int derivedValue;
public DerivedType()
{
derivedValue = 4;
}
protected DerivedType(
SerializationInfo info, StreamingContext context) :
base(info, context)
{
derivedValue = info.GetInt32("derivedValue");
}
[SecurityPermissionAttribute(SecurityAction.Demand,
SerializationFormatter = true)]
public override void GetObjectData(
SerializationInfo info, StreamingContext context)
{
info.AddValue("derivedValue", derivedValue);
base.GetObjectData(info, context);
}
}
}
Related Rules
Implement ISerializable correctly
Implement serialization constructors
Implement serialization methods correctly
Mark all non-serializable fields
Mark ISerializable types with serializable
Provide deserialization methods for optional fields