| Severity | Error |
| Reported by | PostSharp |
| Message | Advice "<Advice>" is not valid on "<Declaration>": this custom attribute is valid only on methods. |
Cause
The advices that transform the target code, such as OnMethodEntryAdvice, OnLocationGetValueAdvice, OnEventAddHandlerAdvice or LocationValidationAdvice, are methods of the aspect class: the custom attribute marks the method that PostSharp invokes. PostSharp reads advice attributes on every member of the aspect class and on the class itself, and reports LA0084 when one of these attributes is on a declaration that is not a method.
The built-in advice attributes can be applied only to methods, so the C# compiler usually reports the mistake first. LocationValidationAdvice is not sealed, though: a class derived from it can declare an AttributeUsageAttribute that allows other targets, and PostSharp handles it as a location validation advice. <Advice> is the type of the custom attribute, and <Declaration> is the declaration that carries it.
In the following example, the [ValidationAdvice] attribute derives from LocationValidationAdvice and is applied to the NotEmptyAttribute aspect class instead of its ValidateValue method.
using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.LA0084_Error;
// A custom advice attribute whose usage also allows classes.
[AttributeUsage( AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = true )]
public sealed class ValidationAdvice : LocationValidationAdvice
{
}
// The advice is applied to the aspect class instead of the validation method.
[ValidationAdvice]
[PSerializable]
public class NotEmptyAttribute : LocationLevelAspect
{
public Exception? ValidateValue( string? value, string locationName, LocationKind locationKind, LocationValidationContext context )
{
return string.IsNullOrEmpty( value ) ? new ArgumentException( $"{locationName} cannot be empty." ) : null;
}
}
public class Customer
{
[NotEmpty]
public string Name { get; set; } = "Alice";
}
public static class Program
{
public static void Main()
{
try
{
new Customer().Name = "";
}
catch ( ArgumentException e )
{
Console.WriteLine( e.Message );
}
}
}
error LA0084: LA0084_Error.cs(18,14): Advice "Errors.LA0084_Error.ValidationAdvice" is not valid on "Errors.LA0084_Error.NotEmptyAttribute": this custom attribute is valid only on methods.
Resolution
Apply the advice attribute to the method that implements the advice. If you derive an advice attribute from LocationValidationAdvice, restrict its AttributeUsageAttribute to AttributeTargets.Method, so that the C# compiler rejects any other target.
In the following example, [ValidationAdvice] is on the ValidateValue method, which validates the Name property of Customer.
using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.LA0084_Fixed;
// A custom advice attribute whose usage also allows classes.
[AttributeUsage( AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = true )]
public sealed class ValidationAdvice : LocationValidationAdvice
{
}
[PSerializable]
public class NotEmptyAttribute : LocationLevelAspect
{
// The advice is applied to the validation method.
[ValidationAdvice]
public Exception? ValidateValue( string? value, string locationName, LocationKind locationKind, LocationValidationContext context )
{
return string.IsNullOrEmpty( value ) ? new ArgumentException( $"{locationName} cannot be empty." ) : null;
}
}
public class Customer
{
[NotEmpty]
public string Name { get; set; } = "Alice";
}
public static class Program
{
public static void Main()
{
try
{
new Customer().Name = "";
}
catch ( ArgumentException e )
{
Console.WriteLine( e.Message );
}
}
}
Name cannot be empty.
See Also
Reference
LocationValidationAdvice
OnMethodEntryAdvice
Other Resources