Open sandboxFocusImprove this doc

LA0167: Aspect Applied to an Unsupported Kind of Declaration

Severity Error
Reported by PostSharp
Message Cannot apply the aspect "<Aspect>" to "<Target>": aspects cannot be applied to a declaration of kind "<DeclarationKind>". Apply the aspect to a declaration of the source code instead. Code that selects the targets of an aspect, such as an IAspectProvider, can skip these declarations by checking MemberInfo.GetSemanticInfo().IsSelectable.

Cause

The C# compiler implements some constructs of the source code with members that it generates: local functions and anonymous methods become methods with generated names, and async methods and iterators become state-machine types. PostSharp does not apply aspects to these declarations, whose IsSelectable property is false. <DeclarationKind> names the kind of the declaration, for example local function, anonymous method or compiler-generated method.

PostSharp reports LA0167 when an aspect reaches such a declaration:

  • A custom attribute of an aspect is applied to a local function, which C# allows since version 9.
  • An IAspectProvider provides an aspect for a member that it found by reflection, such as a method of a closure class or the MoveNext method of a state machine.
  • A location-level aspect is applied to a parameter of a method that cannot receive aspects.

In the following example, the [Log] aspect is applied to the local function Describe. <Target> shows the name of the method that the compiler generated, and the message has no location in the source code.

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

namespace Errors.LA0167_Error;

[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( $"Entering {args.Method.Name}." );
}

public class OrderService
{
    public void PlaceOrder( string product, int quantity )
    {
        // The aspect is applied to a local function.
        [Log]
        string Describe() => $"{quantity} x {product}";

        Console.WriteLine( $"Order placed: {Describe()}." );
    }
}

public static class Program
{
    public static void Main()
    {
        new OrderService().PlaceOrder( "Chair", 4 );
    }
}
error LA0167: LA0167_Error.cs(15,17): Cannot apply the aspect "Errors.LA0167_Error.LogAttribute" to "Errors.LA0167_Error.OrderService.PlaceOrder(System.String, System.Int32).Describe|0_0(Errors.LA0167_Error.OrderService.<>c__DisplayClass0_0@)": aspects cannot be applied to a declaration of kind "local function". Apply the aspect to a declaration of the source code instead. Code that selects the targets of an aspect, such as an IAspectProvider, can skip these declarations by checking MemberInfo.GetSemanticInfo().IsSelectable.

Resolution

  • Turn the local function or the anonymous method into a method of the class, and apply the aspect to this method.
  • Apply the aspect to the method that contains the local function, if the aspect is meant for it.
  • In an aspect provider, skip the members whose GetSemanticInfo returns a SemanticInfo whose IsSelectable property is false.

In the following example, Describe is a private method of OrderService, and the aspect logs its calls.

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

namespace Errors.LA0167_Fixed;

[PSerializable]
public class LogAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( $"Entering {args.Method.Name}." );
}

public class OrderService
{
    public void PlaceOrder( string product, int quantity )
    {
        Console.WriteLine( $"Order placed: {Describe( product, quantity )}." );
    }

    // The local function is now a method of the class, which can receive the aspect.
    [Log]
    private static string Describe( string product, int quantity ) => $"{quantity} x {product}";
}

public static class Program
{
    public static void Main()
    {
        new OrderService().PlaceOrder( "Chair", 4 );
    }
}
Entering Describe.
Order placed: 4 x Chair.

See Also

Reference

SemanticInfo
GetSemanticInfo
IAspectProvider

Other Resources

Adding Aspects Programmatically Using IAspectProvider
Adding Aspects Declaratively Using Attributes