Open sandboxFocusImprove this doc

SR0005: PSerializable Type Already Has a Deserializing Constructor

Severity Error
Reported by PostSharp
Message Cannot apply [PSerializable] to type '<Type>' because it already contains a deserializing constructor, which takes a single parameter of type PortableFormatterConstructorContext. Remove this constructor, because PostSharp generates it.

Cause

[PSerializableAttribute] generates a deserializing constructor in <Type>, which PortableFormatter calls to create the instance before it restores its fields. This constructor has a single parameter of type PortableFormatterConstructorContext. PostSharp reports SR0005 when <Type> already defines a constructor with this signature, whatever its visibility, because the generated constructor would conflict with it.

This usually happens when you write the deserializing constructor yourself, for example to initialize the fields that are not serialized.

In the following example, Customer defines a deserializing constructor to initialize its fullName field, which is marked [PNonSerializedAttribute].

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

namespace Errors.SR0005_Error;

[PSerializable]
public class Customer // Customer already has a deserializing constructor.
{
    [PNonSerialized]
    private string fullName;

    public Customer( string firstName, string lastName )
    {
        this.FirstName = firstName;
        this.LastName = lastName;
        this.fullName = $"{firstName} {lastName}";
    }

    // Written to initialize the field that is not serialized.
    protected Customer( PortableFormatterConstructorContext context )
    {
        this.FirstName = "";
        this.LastName = "";
        this.fullName = "";
    }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName => this.fullName;
}

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

        var customer = (Customer) formatter.Deserialize( stream );
        Console.WriteLine( $"Customer {customer.FullName}" );
    }
}
error SR0005: SR0005_Error.cs(8,14): Cannot apply [PSerializable] to type 'Errors.SR0005_Error.Customer' because it already contains a deserializing constructor, which takes a single parameter of type PortableFormatterConstructorContext. Remove this constructor, because PostSharp generates it.

Resolution

Remove the constructor that takes a PortableFormatterConstructorContext. To initialize the fields that are not serialized, implement ISerializationCallback: PortableFormatter calls its OnDeserialized() method after it has restored the fields of the object.

In the following example, Customer computes its full name in OnDeserialized().

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

namespace Errors.SR0005_Fixed;

[PSerializable]
public class Customer : ISerializationCallback
{
    [PNonSerialized]
    private string fullName;

    public Customer( string firstName, string lastName )
    {
        this.FirstName = firstName;
        this.LastName = lastName;
        this.fullName = $"{firstName} {lastName}";
    }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName => this.fullName;

    // PostSharp generates the deserializing constructor, and the field that is not serialized is initialized here.
    void ISerializationCallback.OnDeserialized() => this.fullName = $"{this.FirstName} {this.LastName}";

    void ISerializationCallback.OnSerializing()
    {
    }
}

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

        var customer = (Customer) formatter.Deserialize( stream );
        Console.WriteLine( $"Customer {customer.FullName}" );
    }
}
Customer Alice Smith

See Also

Reference

PSerializableAttribute
ISerializationCallback
PNonSerializedAttribute
PortableFormatter

Other Resources

Understanding Aspect Serialization