Open sandboxFocusImprove this doc

LA0149: Aspect Serialized with BinaryFormatter Has a Delegate Field

Severity Error
Reported by PostSharp
Message Cannot serialize the delegate type "<DelegateType>": fields of a delegate type in an aspect class must be marked as [NonSerialized].

Cause

PostSharp serializes the aspect instances at build time and deserializes them at run time. An aspect marked as [SerializableAttribute] instead of [PSerializableAttribute] is serialized with BinaryFormatter, which is allowed only when the PostSharpBinaryFormatterAllowed MSBuild property is True (otherwise PostSharp reports LA0206). A delegate refers to a method and often to a closure, which cannot be restored reliably in another process, so PostSharp refuses to serialize it.

PostSharp reports LA0149 when a field of a delegate type holds a delegate at the end of the build-time initialization of the aspect, for example because the constructor or CompileTimeInitialize assigns it. A field that is null at this time does not cause the message. <DelegateType> is the type of the delegate, such as System.Func`2<System.String,System.String>. The message has no location: look for the delegate fields of the [Serializable] aspects of the project.

In the following example, the constructor of the [Log] aspect assigns a lambda to a field.

// @BinaryFormatterAllowed

using System;
using PostSharp.Aspects;

namespace Errors.LA0149_Error;

[Serializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    // The delegate is serialized with the aspect.
    private Func<string, string> format;

    public LogAttribute()
    {
        this.format = name => $"Entering {name}.";
    }

    public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( this.format( args.Method.Name ) );
}

public class OrderService
{
    [Log]
    public void PlaceOrder( string product ) => Console.WriteLine( $"Order placed: {product}" );
}

public static class Program
{
    public static void Main()
    {
        new OrderService().PlaceOrder( "Book" );
    }
}
error LA0149: Cannot serialize the delegate type "System.Func`2<System.String,System.String>": fields of a delegate type in an aspect class must be marked as [NonSerialized].

Resolution

Exclude the field from serialization and create the delegate at run time:

In the following example, the field is excluded from serialization and assigned in RuntimeInitialize(MethodBase). This program builds, but it does not run in an application that disables BinaryFormatter, which is the default on .NET 9 and later.

// @BinaryFormatterAllowed
// @SkipRuntime

using System;
using System.Reflection;
using PostSharp.Aspects;

namespace Errors.LA0149_Fixed;

[Serializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    // The delegate is excluded from serialization and created at run time.
    [NonSerialized]
    private Func<string, string>? format;

    public override void RuntimeInitialize( MethodBase method )
    {
        this.format = name => $"Entering {name}.";
    }

    public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( this.format!( args.Method.Name ) );
}

public class OrderService
{
    [Log]
    public void PlaceOrder( string product ) => Console.WriteLine( $"Order placed: {product}" );
}

public static class Program
{
    public static void Main()
    {
        new OrderService().PlaceOrder( "Book" );
    }
}

See Also

Reference

PSerializableAttribute
PNonSerializedAttribute
NonSerializedAttribute

Other Resources

Understanding Aspect Serialization
Initializing Aspects