107 lines
2.8 KiB
Plaintext
107 lines
2.8 KiB
Plaintext
== 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
|
||
|
||
[source,text]
|
||
----
|
||
public class Foo : ISerializable // Noncompliant the [Serializable] attribute is missing
|
||
{
|
||
}
|
||
----
|
||
or
|
||
|
||
[source,text]
|
||
----
|
||
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
|
||
|
||
[source,text]
|
||
----
|
||
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.
|
||
|