Open sandboxFocusImprove this doc

PS0072: MulticastAttributeUsage More Permissive Than the Base Class

Severity Error
Reported by PostSharp
Message On type "<Type>", [MulticastAttributeUsage] cannot be more permissive than the information inherited from base classes (property <Property>).

Cause

An attribute class inherits the MulticastAttributeUsageAttribute of its base classes, and its own [MulticastAttributeUsage] can only restrict it: a base aspect class relies on the restrictions that it declares, for example on the kinds of declarations that its advices can handle. PostSharp combines the usages from the root base class down to the attribute class, and reports PS0072 when a class allows something that a base class forbids. <Property> names the property of MulticastAttributeUsageAttribute at fault:

<Type> is usually the class whose [MulticastAttributeUsage] is too permissive. Because PostSharp cannot know where the attribute applies, it also stops with PS0055.

In the following example, the TraceAttribute aspect allows constructors, but its base class TraceAspectBase allows methods only.

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

namespace Errors.PS0072_Error;

[PSerializable]
[MulticastAttributeUsage( MulticastTargets.Method )]
public abstract class TraceAspectBase : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"Entering {args.Method.DeclaringType!.Name}.{args.Method.Name}." );
    }
}

// The derived aspect adds constructors to the targets that its base class allows.
[PSerializable]
[MulticastAttributeUsage( MulticastTargets.Method | MulticastTargets.InstanceConstructor )]
public class TraceAttribute : TraceAspectBase
{
}

[Trace]
public class Customer
{
    public Customer( string name )
    {
        this.Name = name;
    }

    public string Name { get; }

    public string Describe() => $"Customer {this.Name}";
}

public static class Program
{
    public static void Main()
    {
        Console.WriteLine( new Customer( "Alice" ).Describe() );
    }
}
error PS0072: PS0072_Error.cs(21,14): On type "Errors.PS0072_Error.TraceAttribute", [MulticastAttributeUsage] cannot be more permissive than the information inherited from base classes (property ValidOn).
error PS0055: The processing of multicast attributes cannot continue because of the previous errors.

Resolution

  • When the base class is yours, and its advices support what the derived class needs, make the [MulticastAttributeUsage] of the base class allow it.
  • Otherwise, remove the property from the [MulticastAttributeUsage] of the derived class, or restrict it to what the base class allows. A base aspect class of PostSharp also declares a usage: for example, OnMethodBoundaryAspect is valid on methods and constructors only.

In the following example, the base class allows constructors too, and the aspect traces the constructor of Customer.

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

namespace Errors.PS0072_Fixed;

// The base class allows every target that the derived aspect needs.
[PSerializable]
[MulticastAttributeUsage( MulticastTargets.Method | MulticastTargets.InstanceConstructor )]
public abstract class TraceAspectBase : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine( $"Entering {args.Method.DeclaringType!.Name}.{args.Method.Name}." );
    }
}

[PSerializable]
[MulticastAttributeUsage( MulticastTargets.Method | MulticastTargets.InstanceConstructor )]
public class TraceAttribute : TraceAspectBase
{
}

[Trace]
public class Customer
{
    public Customer( string name )
    {
        this.Name = name;
    }

    public string Name { get; }

    public string Describe() => $"Customer {this.Name}";
}

public static class Program
{
    public static void Main()
    {
        Console.WriteLine( new Customer( "Alice" ).Describe() );
    }
}
Entering Customer..ctor.
Entering Customer.Describe.
Entering Customer.get_Name.
Customer Alice

See Also

Reference

MulticastAttributeUsageAttribute
MulticastTargets

Other Resources

Understanding Attribute Multicasting
Adding Aspects to Multiple Declarations Using Attributes