| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot apply [PSerializable] to type '<Type>' because it is an interface. |
Cause
[PSerializableAttribute] generates a serializer and a deserializing constructor for the type to which it is applied, and serializes the fields of this type. An interface has neither fields nor constructors, so only classes and structs can be serializable.
C# does not let you write [PSerializable] on an interface. The attribute reaches an interface when it is added programmatically, typically by an aspect that implements IAspectProvider and returns an AspectInstance of PSerializableAttribute for a set of types that includes an interface. PostSharp then reports SR0001 on the interface.
In the following example, an aspect provider makes every type that implements IMessage serializable, and selects the IMessage interface itself.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Serialization;
[assembly: Errors.SR0001_Error.SerializableMessages]
namespace Errors.SR0001_Error;
// Adds [PSerializable] to every message type of the assembly.
[PSerializable]
public class SerializableMessagesAttribute : AssemblyLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
return ((Assembly) targetElement).GetTypes()
.Where( type => typeof(IMessage).IsAssignableFrom( type ) )
.Select( type => new AspectInstance( type, new PSerializableAttribute() ) );
}
}
// The aspect also selects this interface, which cannot be [PSerializable].
public interface IMessage
{
string Describe();
}
public class OrderPlacedMessage : IMessage
{
public int OrderId { get; set; }
public string Describe() => $"Order {this.OrderId} placed";
}
public static class Program
{
public static void Main()
{
var formatter = new PortableFormatter();
var stream = new MemoryStream();
formatter.Serialize( new OrderPlacedMessage { OrderId = 42 }, stream );
stream.Position = 0;
var message = (IMessage) formatter.Deserialize( stream );
Console.WriteLine( message.Describe() );
}
}
error SR0001: SR0001_Error.cs(26,18): Cannot apply [PSerializable] to type 'Errors.SR0001_Error.IMessage' because it is an interface.
Resolution
Exclude the interfaces from the types to which the aspect provider adds [PSerializableAttribute], for example with the IsInterface property, and add the attribute to the classes and structs that implement the interface.
In the following example, the aspect provider skips the interface, and an OrderPlacedMessage is serialized and deserialized with PortableFormatter.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Serialization;
[assembly: Errors.SR0001_Fixed.SerializableMessages]
namespace Errors.SR0001_Fixed;
// Adds [PSerializable] to every message type of the assembly.
[PSerializable]
public class SerializableMessagesAttribute : AssemblyLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
return ((Assembly) targetElement).GetTypes()
// Only classes and structs can be [PSerializable], so the interface is skipped.
.Where( type => typeof(IMessage).IsAssignableFrom( type ) && !type.IsInterface )
.Select( type => new AspectInstance( type, new PSerializableAttribute() ) );
}
}
public interface IMessage
{
string Describe();
}
public class OrderPlacedMessage : IMessage
{
public int OrderId { get; set; }
public string Describe() => $"Order {this.OrderId} placed";
}
public static class Program
{
public static void Main()
{
var formatter = new PortableFormatter();
var stream = new MemoryStream();
formatter.Serialize( new OrderPlacedMessage { OrderId = 42 }, stream );
stream.Position = 0;
var message = (IMessage) formatter.Deserialize( stream );
Console.WriteLine( message.Describe() );
}
}
Order 42 placed
See Also
Reference
PSerializableAttribute
IAspectProvider
PortableFormatter
Other Resources
Understanding Aspect Serialization
Adding Aspects Dynamically