| Severity | Error |
| Reported by | PostSharp |
| Message | The type "<Type>" or one of its ancestors should be decorated by an instance of MulticastAttributeUsageAttribute. |
Cause
PostSharp multicasts an attribute derived from MulticastAttribute to the declarations that its MulticastAttributeUsageAttribute allows: for example, from a class to its methods. See Understanding Attribute Multicasting. An attribute class inherits this usage from its base classes. The aspect classes of PostSharp, such as OnMethodBoundaryAspect, already carry one, but MulticastAttribute itself does not.
PostSharp reports PS0051 on the attribute class <Type> when you apply it in the project, and neither the class nor any of its base classes carry a MulticastAttributeUsageAttribute. This usually happens with a class derived directly from MulticastAttribute, for example a marker attribute that you want to multicast without adding any behavior. PostSharp then skips the instances of the attribute, and reports PS0055 because it cannot continue after this error.
In the following example, the [Audited] marker attribute derives directly from MulticastAttribute.
// @DisabledMessages(PS0131)
using System;
using System.Linq;
using System.Reflection;
using PostSharp.Extensibility;
namespace Errors.PS0051_Error;
// This multicast attribute does not say on which declarations it can be applied.
public sealed class AuditedAttribute : MulticastAttribute
{
}
[Audited]
public class OrderService
{
public void PlaceOrder( string product )
{
Console.WriteLine( $"Order placed for {product}." );
}
public void CancelOrder( string product )
{
Console.WriteLine( $"Order canceled for {product}." );
}
}
public static class Program
{
public static void Main()
{
var auditedMethods = typeof(OrderService)
.GetMethods( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly )
.Where( m => m.IsDefined( typeof(AuditedAttribute) ) )
.Select( m => m.Name )
.OrderBy( n => n );
Console.WriteLine( $"Audited methods: {string.Join( ", ", auditedMethods )}." );
}
}
error PS0051: PS0051_Error.cs(11,21): The type "Errors.PS0051_Error.AuditedAttribute" or one of its ancestors should be decorated by an instance of MulticastAttributeUsageAttribute.
error PS0055: The processing of multicast attributes cannot continue because of the previous errors.
Resolution
Add a MulticastAttributeUsageAttribute to the attribute class, or to a base class of it, and set its ValidOn property to the kinds of declarations on which the attribute can end up. By default, the compiled assembly does not contain the instances of a multicast attribute: set PersistMetaData to true when the program reads the attribute with reflection. See Reflecting Aspect Instances at Run Time.
In the following example, the [Audited] attribute applied to OrderService is multicast to its two methods, where the program finds it.
// @DisabledMessages(PS0131)
using System;
using System.Linq;
using System.Reflection;
using PostSharp.Extensibility;
namespace Errors.PS0051_Fixed;
// The usage says that the attribute multicasts to methods and stays in the assembly.
[MulticastAttributeUsage( MulticastTargets.Method, PersistMetaData = true )]
public sealed class AuditedAttribute : MulticastAttribute
{
}
[Audited]
public class OrderService
{
public void PlaceOrder( string product )
{
Console.WriteLine( $"Order placed for {product}." );
}
public void CancelOrder( string product )
{
Console.WriteLine( $"Order canceled for {product}." );
}
}
public static class Program
{
public static void Main()
{
var auditedMethods = typeof(OrderService)
.GetMethods( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly )
.Where( m => m.IsDefined( typeof(AuditedAttribute) ) )
.Select( m => m.Name )
.OrderBy( n => n );
Console.WriteLine( $"Audited methods: {string.Join( ", ", auditedMethods )}." );
}
}
Audited methods: CancelOrder, PlaceOrder.
See Also
Reference
MulticastAttributeUsageAttribute
MulticastAttribute
Other Resources
Understanding Attribute Multicasting
Adding Aspects to Multiple Declarations Using Attributes
Reflecting Aspect Instances at Run Time