rspec/rules/S3925/rule.adoc

105 lines
2.8 KiB
Plaintext
Raw Normal View History

2021-01-27 13:42:22 +01:00
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.
2020-06-30 12:48:39 +02:00
2021-02-02 15:02:10 +01:00
2021-01-27 13:42:22 +01:00
This rules raises an issue on types that implement ``++ISerializable++`` without following the serialization pattern recommended by Microsoft.
2020-06-30 12:48:39 +02:00
2021-02-02 15:02:10 +01:00
2020-06-30 12:48:39 +02:00
Specifically this rule checks for these problems:
2021-01-27 13:42:22 +01:00
* The ``++System.SerializableAttribute++`` attribute is missing.
* Non-serializable fields are not marked with the ``++System.NonSerializedAttribute++`` attribute.
2020-06-30 12:48:39 +02:00
* There is no serialization constructor.
2021-01-27 13:42:22 +01:00
* 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++``.
2021-01-27 13:42:22 +01:00
* 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++``.
2020-06-30 12:48:39 +02:00
== Noncompliant Code Example
2022-02-04 17:28:24 +01:00
[source,text]
2020-06-30 12:48:39 +02:00
----
public class Foo : ISerializable // Noncompliant the [Serializable] attribute is missing
{
}
----
or
2022-02-04 17:28:24 +01:00
[source,text]
2020-06-30 12:48:39 +02:00
----
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
2022-02-04 17:28:24 +01:00
[source,text]
2020-06-30 12:48:39 +02:00
----
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.