Open sandboxFocusImprove this doc

SR0009: Serializer of the Base Type Is Not Visible from the Derived Type

Severity Error
Reported by PostSharp
Message Cannot apply [PSerializable] to type '<Type>' because the serializer '<Serializer>' is not visible from '<Type>'.

Cause

When a [PSerializableAttribute] class derives from a class whose serializer is written by hand, the serializer that PostSharp generates for the derived class is a nested class of <Type> that derives from the serializer of the base class. A class can derive only from a class that it can see, so the serializer of the base class must be visible from <Type>.

PostSharp reports SR0009 on <Type> when the serializer <Serializer> of its base class is not visible from it: typically a private nested class of the base class.

In the following example, EntitySerializer is a private nested class of Entity, so Customer cannot see it.

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

namespace Errors.SR0009_Error;

[Serializer( typeof(EntitySerializer) )]
public class Entity
{
    public int Id { get; set; }

    public Entity() { }

    // The deserializing constructor, which the serializer of Customer calls.
    protected Entity( PortableFormatterConstructorContext context ) { }

    private 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 // The private EntitySerializer is not visible from Customer.
{
    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 SR0009: SR0009_Error.cs(30,14): Cannot apply [PSerializable] to type 'Errors.SR0009_Error.Customer' because the serializer 'Errors.SR0009_Error.Entity.EntitySerializer' is not visible from 'Errors.SR0009_Error.Customer'.

Resolution

Make the serializer of the base class visible from the derived classes, for example protected or public when it is nested in the base class.

In the following example, EntitySerializer is protected, and a Customer is serialized and deserialized with its Id and its Name.

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

namespace Errors.SR0009_Fixed;

[Serializer( typeof(EntitySerializer) )]
public class Entity
{
    public int Id { get; set; }

    public Entity() { }

    // The deserializing constructor, which the serializer of Customer calls.
    protected Entity( PortableFormatterConstructorContext context ) { }

    // Protected, so the serializer is visible from Customer.
    protected 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
ReferenceTypeSerializer
SerializerAttribute

Other Resources

Understanding Aspect Serialization