Open sandboxFocusImprove this doc

SR0006: Base Type of a PSerializable Type Is Not Serializable

Severity Error
Reported by PostSharp
Message Cannot apply [PSerializable] to type '<Type>' because its base type is not serializable: it has neither a [PSerializable] or [Serializer] attribute nor a nested Serializer class. Apply [PSerializable] to the base type.

Cause

[PSerializableAttribute] generates a serializer for <Type> that serializes the fields declared in <Type>, and extends the serializer of the base type for the fields that the base type declares. The base type must therefore have a serializer, given by one of:

  • [PSerializableAttribute], which generates it;
  • [SerializerAttribute], which names a serializer written by hand, or no serializer with [Serializer(null)] when the base type has no state to serialize;
  • a nested class named Serializer, written by hand.

The base types object, ValueType, Attribute and MarshalByRefObject do not need a serializer. PostSharp reports SR0006 when the direct base type of <Type> is another type that has none of the three. This includes most classes of .NET and of other libraries.

In the following example, Customer is [PSerializableAttribute], but its base class Entity is not.

using System;
using System.IO;
using PostSharp.Serialization;

namespace Errors.SR0006_Error;

public class Entity
{
    public int Id { get; set; }
}

[PSerializable]
public class Customer : Entity // Entity is not serializable.
{
    public string? Name { get; set; }
}

public static class Program
{
    public static void Main()
    {
        var formatter = new PortableFormatter();
        var stream = new MemoryStream();
        formatter.Serialize( new Customer { Id = 1, Name = "Alice" }, stream );
        stream.Position = 0;

        var customer = (Customer) formatter.Deserialize( stream );
        Console.WriteLine( $"Customer {customer.Id}: {customer.Name}" );
    }
}
error SR0006: SR0006_Error.cs(13,14): Cannot apply [PSerializable] to type 'Errors.SR0006_Error.Customer' because its base type is not serializable: it has neither a [PSerializable] or [Serializer] attribute nor a nested Serializer class. Apply [PSerializable] to the base type.

Resolution

  • Apply [PSerializableAttribute] to the base type. PostSharp then generates its serializer, which the serializer of the derived type extends.
  • When the base type has no state to serialize, mark it with [Serializer(null)], and give it a parameterless constructor that the derived type can access.
  • When you cannot change the base type, for example because it is a class of another library, do not derive from it: keep an instance of it in a field, write a serializer for its type, and declare this serializer with ImportSerializerAttribute.

In the following example, Entity is [PSerializableAttribute], and a Customer is serialized and deserialized with its Id and its Name.

using System;
using System.IO;
using PostSharp.Serialization;

namespace Errors.SR0006_Fixed;

// PostSharp generates the serializer of the base class too.
[PSerializable]
public class Entity
{
    public int Id { get; set; }
}

[PSerializable]
public class Customer : Entity
{
    public string? Name { get; set; }
}

public static class Program
{
    public static void Main()
    {
        var formatter = new PortableFormatter();
        var stream = new MemoryStream();
        formatter.Serialize( new Customer { Id = 1, Name = "Alice" }, stream );
        stream.Position = 0;

        var customer = (Customer) formatter.Deserialize( stream );
        Console.WriteLine( $"Customer {customer.Id}: {customer.Name}" );
    }
}
Customer 1: Alice

See Also

Reference

PSerializableAttribute
SerializerAttribute
PortableFormatter

Other Resources

Understanding Aspect Serialization