rspec/rules/S3925/rule.adoc

107 lines
2.8 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

== 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 dont 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.