Why is this an issue?
The ISerializable
interface is the mechanism to control the type serialization process. If not implemented correctly this could result
in an invalid serialization and hard to detect bugs.
This rules raises an issue on types that implement ISerializable
without following the serialization pattern recommended by
Microsoft.
Specifically this rule checks for these problems:
- The
System.SerializableAttribute
attribute is missing.
- Non-serializable fields are not marked with the
System.NonSerializedAttribute
attribute.
- There is no serialization constructor.
- An unsealed type has a serialization constructor that is not
protected
.
- A sealed type has a serialization constructor that is not
private
.
- An unsealed type has a
ISerializable.GetObjectData
that is not both public
and virtual
.
- A derived type has a serialization constructor that does not call the
base
constructor.
- A derived type has a
ISerializable.GetObjectData
method that does not call the base
method.
- A derived type has serializable fields but the
ISerializable.GetObjectData
method is not overridden.
Classes which inherit from Exception
are implementing ISerializable
. Make sure [Serializable]
attribute is
used and that ISerializable
is correctly implemented. Even it you don’t plan to explicitly serialize the object yourself, it
might still require serialization, for instance when crossing the boundary of an AppDomain
.
Noncompliant code example
public class Foo : ISerializable // Noncompliant the [Serializable] attribute is missing
{
}
or
public class Bar
{
}
[Serializable]
public class Foo : ISerializable // Noncompliant the serialization constructor is missing
{
private readonly Bar bar; // Noncompliant the field is not marked with [NonSerialized]
}
Compliant solution
public class Bar
{
}
[Serializable]
public class Foo : ISerializable
{
[NonSerialized]
private readonly Bar bar;
public Foo()
{
// ...
}
protected Foo(SerializationInfo info, StreamingContext context)
{
// ...
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
// ...
}
}
[Serializable]
public sealed class SubFoo : Foo
{
private int val;
public SubFoo()
{
// ...
}
private SubFoo(SerializationInfo info, StreamingContext context)
: base(info, context)
{
// ...
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
// ...
}
}
Exceptions
- Classes in test projects are not checked.