| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot apply [PSerializable] to type '<Type>' because the default constructor of the serializer '<Serializer>' is not accessible from the serializer generated for '<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 derives from the serializer of the base class, and its constructor calls the parameterless constructor of the base serializer. This constructor must be accessible from the generated serializer.
PostSharp reports SR0011 on the parameterless constructor of <Serializer> when the serializer generated for <Type> cannot call it, typically because it is private. A base serializer that has no parameterless constructor at all is reported with SR0010 instead.
In the following example, the default constructor of EntitySerializer is private.
using System;
using System.IO;
using PostSharp.Serialization;
namespace Errors.SR0011_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 ) { }
// A serializer written by hand, which the serializer generated for Customer extends.
protected class EntitySerializer : ReferenceTypeSerializer
{
// Private, so the serializer of Customer cannot call it.
private EntitySerializer() { }
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 SR0011: SR0011_Error.cs(34,14): Cannot apply [PSerializable] to type 'Errors.SR0011_Error.Customer' because the default constructor of the serializer 'Errors.SR0011_Error.Entity.EntitySerializer' is not accessible from the serializer generated for 'Errors.SR0011_Error.Customer'.
Resolution
Make the parameterless constructor of the base serializer protected or public.
In the following example, the default constructor of 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.SR0011_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 ) { }
// A serializer written by hand, which the serializer generated for Customer extends.
protected class EntitySerializer : ReferenceTypeSerializer
{
// Protected, so the serializer of Customer can call it.
protected EntitySerializer() { }
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