Open sandboxFocusImprove this doc

LA0230: Group of an Advice Cannot Be Inferred

Severity Error
Reported by PostSharp
Message The group of the advice "<Advice>" cannot be inferred because several groups of "<AspectClass>" have no advice of its kind yet: the groups of <Groups>. Set the Group property of the advice and of the advices of the group that it must join to the same value.

Cause

Advices of the same family, such as the method boundary advices, are woven in groups. PostSharp forms the groups of each class of the aspect separately. An advice with a pointcut starts a group, and an advice with the Group property joins the group of this name. An advice that has neither joins the group of its class that has no advice of its kind yet, or starts a group that applies to the target of the aspect when every group of the class already has one.

When several groups of the class have no advice of its kind, for instance two groups started by entry advices with different pointcuts and one exit advice, PostSharp does not choose between them, and reports LA0230 on the advice. Declaration order never decides. <AspectClass> is the class that declares the advice, and <Groups> names the first advice of each candidate group.

In the following example, the aspect has an entry advice for the getters and another for the setters, and an exit advice without pointcut and without Group.

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

namespace Errors.LA0230_Error;

[PSerializable]
public class MonitorAttribute : TypeLevelAspect
{
    [OnMethodEntryAdvice, MulticastPointcut( MemberName = "Get*" )]
    public void OnGetterEntry()
    {
        Console.WriteLine( "A getter started." );
    }

    [OnMethodEntryAdvice, MulticastPointcut( MemberName = "Set*" )]
    public void OnSetterEntry()
    {
        Console.WriteLine( "A setter started." );
    }

    // Neither group has an exit advice, so PostSharp cannot tell which group this advice joins.
    [OnMethodExitAdvice]
    public void OnGetterExit()
    {
        Console.WriteLine( "A getter completed." );
    }
}

[Monitor]
public class Settings
{
    private string theme = "Light";

    public string GetTheme() => this.theme;

    public void SetTheme( string theme ) => this.theme = theme;
}

public static class Program
{
    public static void Main()
    {
        var settings = new Settings();
        settings.SetTheme( "Dark" );
        Console.WriteLine( settings.GetTheme() );
    }
}
error LA0230: LA0230_Error.cs(25,17): The group of the advice "Errors.LA0230_Error.MonitorAttribute.OnGetterExit" cannot be inferred because several groups of "Errors.LA0230_Error.MonitorAttribute" have no advice of its kind yet: the groups of Errors.LA0230_Error.MonitorAttribute.OnGetterEntry, Errors.LA0230_Error.MonitorAttribute.OnSetterEntry. Set the Group property of the advice and of the advices of the group that it must join to the same value.

Resolution

  • Set the Group property of the advice, and the same value on the advices of the group that it must join. Setting it on the advice alone gives the advice a new group without pointcut, which applies to the target of the aspect.
  • Or give the advice a pointcut, when it must start a group of its own.

In the following example, the Getters group name puts the exit advice in the group of the getters.

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

namespace Errors.LA0230_Fixed;

[PSerializable]
public class MonitorAttribute : TypeLevelAspect
{
    [OnMethodEntryAdvice( Group = "Getters" ), MulticastPointcut( MemberName = "Get*" )]
    public void OnGetterEntry()
    {
        Console.WriteLine( "A getter started." );
    }

    [OnMethodEntryAdvice, MulticastPointcut( MemberName = "Set*" )]
    public void OnSetterEntry()
    {
        Console.WriteLine( "A setter started." );
    }

    // The Group property puts the advice in the group of OnGetterEntry.
    [OnMethodExitAdvice( Group = "Getters" )]
    public void OnGetterExit()
    {
        Console.WriteLine( "A getter completed." );
    }
}

[Monitor]
public class Settings
{
    private string theme = "Light";

    public string GetTheme() => this.theme;

    public void SetTheme( string theme ) => this.theme = theme;
}

public static class Program
{
    public static void Main()
    {
        var settings = new Settings();
        settings.SetTheme( "Dark" );
        Console.WriteLine( settings.GetTheme() );
    }
}
A setter started.
A getter started.
A getter completed.
Dark

See Also

Reference

Group
MulticastPointcut

Other Resources

Selecting Members with Pointcuts
Advice Methods