| Severity | Error |
| Reported by | PostSharp |
| Message | Method '<Method>' cannot be sealed because it must be overridden by the serializer of type '<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 <Type> derives from the serializer of the base class. It overrides SerializeObject and DeserializeFields to serialize the fields of <Type>, and calls the implementations of the base serializer for the fields of the base class.
PostSharp reports SR0012 on <Method> when the base serializer overrides one of these two methods as sealed.
In the following example, EntitySerializer seals SerializeObject.
using System;
using System.IO;
using PostSharp.Serialization;
namespace Errors.SR0012_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
{
public override object CreateInstance( Type type, IArgumentsReader constructorArguments ) => new Entity();
// The serializer of Customer cannot override a sealed method.
public sealed 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 SR0012: SR0012_Error.cs(23,37): Method 'Errors.SR0012_Error.Entity.EntitySerializer.SerializeObject(System.Object, PostSharp.Serialization.IArgumentsWriter, PostSharp.Serialization.IArgumentsWriter)' cannot be sealed because it must be overridden by the serializer of type 'Errors.SR0012_Error.Customer'.
Resolution
Remove the sealed modifier from SerializeObject and DeserializeFields in the serializer of the base type.
In the following example, SerializeObject is not sealed, and a Customer is serialized and deserialized with its Id and its Name.
using System;
using System.IO;
using PostSharp.Serialization;
namespace Errors.SR0012_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
{
public override object CreateInstance( Type type, IArgumentsReader constructorArguments ) => new Entity();
// Not sealed, so that the serializer of Customer can override it.
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