| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot apply the aspect "<Aspect>" to "<Target>": this aspect must be applied to <DeclarationKind>. |
Cause
Each kind of aspect works on one kind of declaration: a MethodLevelAspect, such as an OnMethodBoundaryAspect, on a method; a TypeLevelAspect on a type; a LocationInterceptionAspect on a field or a property; and so on. When you apply an aspect as a custom attribute, multicasting already skips the declarations that the aspect does not support. An aspect that an IAspectProvider provides is not filtered this way: its target is the declaration passed to the AspectInstance constructor. When this declaration is of a kind that the aspect does not support, PostSharp reports LA0099 on it and skips the aspect.
<DeclarationKind> is the kind of declaration that the aspect supports, such as a method or a type.
In the following example, the [LogMethods] aspect provider passes its own target, the OrderService class, to the [Log] method-level aspect.
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0099_Error;
[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args )
{
Console.WriteLine( $"Entering {args.Method.Name}." );
}
}
[PSerializable]
public class LogMethodsAttribute : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
// The method-level aspect is provided to the type instead of its methods.
yield return new AspectInstance( targetElement, new LogAttribute() );
}
}
[LogMethods]
public class OrderService
{
public void PlaceOrder() => Console.WriteLine( "Order placed." );
public void CancelOrder() => Console.WriteLine( "Order canceled." );
}
public static class Program
{
public static void Main()
{
var service = new OrderService();
service.PlaceOrder();
service.CancelOrder();
}
}
error LA0099: LA0099_Error.cs(29,14): Cannot apply the aspect "Errors.LA0099_Error.LogAttribute" to "Errors.LA0099_Error.OrderService": this aspect must be applied to a method.
Resolution
In the ProvideAspects method, select the declarations that the provided aspect supports: for a method-level aspect, the methods of the target type, from GetMethods; for a location aspect, its fields or properties. Otherwise, provide another kind of aspect, one that supports the target.
In the following example, the provider passes each public method of the class to the [Log] aspect.
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0099_Fixed;
[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args )
{
Console.WriteLine( $"Entering {args.Method.Name}." );
}
}
[PSerializable]
public class LogMethodsAttribute : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
var type = (Type) targetElement;
// The method-level aspect is provided to each method of the type.
foreach ( var method in type.GetMethods( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly ) )
{
yield return new AspectInstance( method, new LogAttribute() );
}
}
}
[LogMethods]
public class OrderService
{
public void PlaceOrder() => Console.WriteLine( "Order placed." );
public void CancelOrder() => Console.WriteLine( "Order canceled." );
}
public static class Program
{
public static void Main()
{
var service = new OrderService();
service.PlaceOrder();
service.CancelOrder();
}
}
Entering PlaceOrder.
Order placed.
Entering CancelOrder.
Order canceled.
See Also
Reference
IAspectProvider
AspectInstance
MethodLevelAspect
Other Resources