Open sandboxFocusImprove this doc

PS0065: Attribute That Allows a Single Instance Is Declared Several Times

Severity Error
Reported by PostSharp
Message Multiple instances of the custom attribute "<Attribute>" are declared on "<Declaration>", but the attribute has MulticastAttributeUsage.AllowMultiple = false.

Cause

The AllowMultiple property of the MulticastAttributeUsageAttribute of an aspect class says whether a declaration can receive several instances of the aspect. When it is false, and an instance multicast from a container, such as a class or the assembly, reaches a declaration that already has one, the new instance overrides the previous one: see Overriding and Removing Aspect Instances.

PostSharp cannot choose between two instances that are declared directly on the same declaration, so it reports PS0065. This check is distinct from the AllowMultiple property of the AttributeUsageAttribute of C#: the base aspect classes of PostSharp, such as OnMethodBoundaryAspect, allow several instances for C#, so the C# compiler accepts the duplicate attributes and only PostSharp rejects them.

PostSharp reports the message on the declaration that has the attributes. <Attribute> is the full name of the attribute class.

In the following example, the PlaceOrder method has two [Trace] aspects, and the [MulticastAttributeUsage] of the TraceAttribute class allows only one.

using System;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Serialization;

namespace Errors.PS0065_Error;

[PSerializable]
[MulticastAttributeUsage( MulticastTargets.Method, AllowMultiple = false )]
public class TraceAttribute : OnMethodBoundaryAspect
{
    public TraceAttribute( string category )
    {
        this.Category = category;
    }

    public string Category { get; set; }

    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"[{this.Category}] Entering {args.Method.Name}." );
    }
}

public class OrderService
{
    // The method has two instances of an aspect that allows only one.
    [Trace( "Orders" )]
    [Trace( "Billing" )]
    public void PlaceOrder() => Console.WriteLine( "Order placed." );
}

public static class Program
{
    public static void Main()
    {
        new OrderService().PlaceOrder();
    }
}
error PS0065: PS0065_Error.cs(30,17): Multiple instances of the custom attribute "Errors.PS0065_Error.TraceAttribute" are declared on "Errors.PS0065_Error.OrderService.PlaceOrder", but the attribute has MulticastAttributeUsage.AllowMultiple = false.

Resolution

  • Remove the extra instances, so that the declaration has a single instance of the attribute.
  • When the attribute is designed to be applied several times to the same declaration, set AllowMultiple to true in the [MulticastAttributeUsage] of the attribute class, or remove the property. PostSharp then applies every instance. A base class that sets AllowMultiple to false cannot be overridden this way: PostSharp reports PS0072.

In the following example, the PlaceOrder method has a single [Trace] aspect.

using System;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Serialization;

namespace Errors.PS0065_Fixed;

[PSerializable]
[MulticastAttributeUsage( MulticastTargets.Method, AllowMultiple = false )]
public class TraceAttribute : OnMethodBoundaryAspect
{
    public TraceAttribute( string category )
    {
        this.Category = category;
    }

    public string Category { get; set; }

    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"[{this.Category}] Entering {args.Method.Name}." );
    }
}

public class OrderService
{
    // The method has a single instance of the aspect.
    [Trace( "Orders" )]
    public void PlaceOrder() => Console.WriteLine( "Order placed." );
}

public static class Program
{
    public static void Main()
    {
        new OrderService().PlaceOrder();
    }
}
[Orders] Entering PlaceOrder.
Order placed.

See Also

Reference

MulticastAttributeUsageAttribute
AllowMultiple

Other Resources

Overriding and Removing Aspect Instances
Adding Aspects to Multiple Declarations Using Attributes