Open sandboxFocusImprove this doc

SR0013: Serializer of the Base Type Is Sealed

Severity Error
Reported by PostSharp
Message Class '<BaseSerializer>' cannot be sealed because the serializer of type '<Type>' must derive from it.

Cause

[PSerializableAttribute] generates a serializer class for the type <Type>. When <Type> derives from a class that has its own serializer, the generated serializer derives from this serializer, so that the fields of the base class are serialized by the code written for them.

The serializer of the base class is the class named by its [SerializerAttribute] attribute, or its nested class named Serializer. PostSharp reports SR0013, on the serializer class <BaseSerializer>, when this class is sealed.

In the following example, Entity has a hand-written serializer, EntitySerializer, which is sealed, and the [PSerializable] class Customer derives from Entity.

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

namespace Errors.SR0013_Error;

[Serializer( typeof(Entity.EntitySerializer) )]
public class Entity
{
    public Entity()
    {
    }

    protected Entity( PortableFormatterConstructorContext context )
    {
    }

    public int Id { get; set; }

    // The serializer of Customer must derive from this class, which is sealed.
    public sealed class EntitySerializer : ReferenceTypeSerializer
    {
        public override object CreateInstance( Type type, IArgumentsReader constructorArguments ) => new Entity();

        public override void SerializeObject( object obj, IArgumentsWriter constructorArguments, IArgumentsWriter initializationArguments )
            => initializationArguments.SetValue( "Id", ((Entity) obj).Id );

        public override void DeserializeFields( object obj, IArgumentsReader initializationArguments )
            => ((Entity) obj).Id = initializationArguments.GetValue<int>( "Id" );
    }
}

[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}" );
    }
}
error SR0013: SR0013_Error.cs(21,25): Class 'Errors.SR0013_Error.Entity.EntitySerializer' cannot be sealed because the serializer of type 'Errors.SR0013_Error.Customer' must derive from it.

Resolution

Remove the sealed modifier from the serializer class of the base type. Its <xref:PostSharp.Serialization.ReferenceTypeSerializer.SerializeObject> and <xref:PostSharp.Serialization.ReferenceTypeSerializer.DeserializeFields> methods must not be sealed either, or PostSharp reports SR0012.

In the following example, EntitySerializer is not sealed, and a Customer is serialized and deserialized with PortableFormatter.

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

namespace Errors.SR0013_Fixed;

[Serializer( typeof(Entity.EntitySerializer) )]
public class Entity
{
    public Entity()
    {
    }

    protected Entity( PortableFormatterConstructorContext context )
    {
    }

    public int Id { get; set; }

    // The class is not sealed, so the serializer of Customer derives from it.
    public class EntitySerializer : ReferenceTypeSerializer
    {
        public override object CreateInstance( Type type, IArgumentsReader constructorArguments ) => new Entity();

        public override void SerializeObject( object obj, IArgumentsWriter constructorArguments, IArgumentsWriter initializationArguments )
            => initializationArguments.SetValue( "Id", ((Entity) obj).Id );

        public override void DeserializeFields( object obj, IArgumentsReader initializationArguments )
            => ((Entity) obj).Id = initializationArguments.GetValue<int>( "Id" );
    }
}

[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
ReferenceTypeSerializer
PortableFormatter

Other Resources

Understanding Aspect Serialization