| Severity | Warning |
| Reported by | PostSharp |
| Message | The property <Property> on <Attribute> does nothing when annotating <Declaration>. It only works when applied to <LegalTargets>. |
Cause
A multicast attribute, such as an aspect, can filter the declarations that it is multicast to by name. Each filter selects among the children of the declaration that the attribute is applied to, so it is meaningful only on some declarations:
| Property | Has an effect when the attribute is applied to |
|---|---|
| AttributeTargetAssemblies | an assembly |
| AttributeTargetTypes | an assembly |
| AttributeTargetMembers | an assembly or a type |
PostSharp reports PS0276 when the attribute sets one of these properties on another declaration, for example AttributeTargetTypes on a class, or AttributeTargetMembers on a method. PostSharp ignores the property and multicasts the attribute as if the property were not set. <LegalTargets> names the declarations on which the property has an effect. The warning is reported on the declaration that carries the attribute.
This usually happens when an attribute written for the assembly level is copied onto a type.
In the following example, the [Log] aspect is applied to the OrderService class with a type filter that should select every service. The filter is ignored, so the aspect applies to the methods of OrderService only.
using System;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.PS0276_Error;
[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args )
=> Console.WriteLine( $"Entering {args.Method.DeclaringType!.Name}.{args.Method.Name}." );
}
// AttributeTargetTypes has no effect on a type: the aspect applies to OrderService only.
[Log( AttributeTargetTypes = "Errors.PS0276_Error.*Service" )]
public class OrderService
{
public void PlaceOrder( int orderId ) => Console.WriteLine( $"Order {orderId} placed." );
}
public class CustomerService
{
public void Register( string name ) => Console.WriteLine( $"Customer {name} registered." );
}
public static class Program
{
public static void Main()
{
new OrderService().PlaceOrder( 42 );
new CustomerService().Register( "Alice" );
}
}
warning PS0276: PS0276_Error.cs(16,14): The property AttributeTargetTypes on Errors.PS0276_Error.LogAttribute does nothing when annotating Errors.PS0276_Error.OrderService. It only works when applied to an assembly.
The program shows that CustomerService is not logged:
Entering OrderService..ctor.
Entering OrderService.PlaceOrder.
Order 42 placed.
Customer Alice registered.
Resolution
- When the filter must select types or assemblies, move the attribute to the assembly, with the
[assembly: ...]syntax. - When the attribute is in the right place, remove the property: the declaration that the attribute is applied to already decides which types or members it reaches.
See Adding Aspects to Multiple Declarations Using Attributes for the ways to filter the targets of an aspect.
In the following example, the aspect is applied to the assembly, and its type filter selects both services.
using System;
using PostSharp.Aspects;
using PostSharp.Serialization;
// On the assembly, AttributeTargetTypes selects every type whose name matches the pattern.
[assembly: Errors.PS0276_Fixed.Log( AttributeTargetTypes = "Errors.PS0276_Fixed.*Service" )]
namespace Errors.PS0276_Fixed;
[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args )
=> Console.WriteLine( $"Entering {args.Method.DeclaringType!.Name}.{args.Method.Name}." );
}
public class OrderService
{
public void PlaceOrder( int orderId ) => Console.WriteLine( $"Order {orderId} placed." );
}
public class CustomerService
{
public void Register( string name ) => Console.WriteLine( $"Customer {name} registered." );
}
public static class Program
{
public static void Main()
{
new OrderService().PlaceOrder( 42 );
new CustomerService().Register( "Alice" );
}
}
Entering OrderService..ctor.
Entering OrderService.PlaceOrder.
Order 42 placed.
Entering CustomerService..ctor.
Entering CustomerService.Register.
Customer Alice registered.
See Also
Reference
MulticastAttribute
AttributeTargetTypes
AttributeTargetMembers
AttributeTargetAssemblies
Other Resources
Adding Aspects to Multiple Declarations Using Attributes
Understanding Attribute Multicasting