Open sandboxFocusImprove this doc

LA0267: Property or Event Object Outside an Instance-Scoped Advice

Severity Error
Reported by PostSharp
Message The parameter "<Parameter>" of the advice "<Advice>" is bound by [ImportMember] and is of type "<ParameterType>", which is bound to one object. Property<T> and Event<T> are supported only on the instance advices of an instance-scoped aspect, whose aspect instance belongs to one object. Use ILocationBinding<T>, or import the event as a field of the aspect.

Cause

An advice parameter of type Property<TValue> or Event<TDelegate> annotated with ImportMemberAttribute receives delegates that read and write a property, or add and remove handlers of an event, of one target object. PostSharp creates these objects once per target object, so only an advice that runs for one object can receive them: an instance method of an aspect that implements IInstanceScopedAspect, such as an InstanceLevelAspect, whose aspect instance belongs to one object.

PostSharp reports LA0267 in the following cases:

  • The advice is a static method, even in an instance-scoped aspect.
  • The aspect is statically scoped, for example a MethodLevelAspect that does not implement IInstanceScopedAspect: one aspect instance serves all the objects of the target type.

In the following example, the [LogStatus] aspect is a statically scoped MethodLevelAspect, and its advice imports the Status property as a Property<TValue>.

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

namespace Errors.LA0267_Error;

[PSerializable]
public class LogStatusAttribute : MethodLevelAspect
{
    // MethodLevelAspect is statically scoped: one aspect instance serves all the Order objects.
    [OnMethodEntryAdvice]
    public void OnEntry( [This] object instance, [DeclarationName] string methodName,
                         [ImportMember( "Status", IsRequired = true )] Property<string> status )
    {
        Console.WriteLine( $"{methodName}: status of the {instance.GetType().Name} is {status.Get()}." );
    }
}

public class Order
{
    public string Status { get; private set; } = "New";

    [LogStatus]
    public void Ship()
    {
        this.Status = "Shipped";
        Console.WriteLine( "Order shipped." );
    }
}

public static class Program
{
    public static void Main()
    {
        new Order().Ship();
    }
}
error LA0267: LA0267_Error.cs(14,89): The parameter "status" of the advice "Errors.LA0267_Error.LogStatusAttribute.OnEntry(System.Object, System.String, PostSharp.Aspects.Advices.Property<System.String>)" is bound by [ImportMember] and is of type "PostSharp.Aspects.Advices.Property`1<string>", which is bound to one object. Property<T> and Event<T> are supported only on the instance advices of an instance-scoped aspect, whose aspect instance belongs to one object. Use ILocationBinding<T>, or import the event as a field of the aspect.

Resolution

In the following example, the aspect stays statically scoped and imports Status as an ILocationBinding<T>.

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

namespace Errors.LA0267_Fixed;

[PSerializable]
public class LogStatusAttribute : MethodLevelAspect
{
    // ILocationBinding<string> reads the property of the object passed to GetValue.
    [OnMethodEntryAdvice]
    public void OnEntry( [This] object instance, [DeclarationName] string methodName,
                         [ImportMember( "Status", IsRequired = true )] ILocationBinding<string> status )
    {
        Console.WriteLine( $"{methodName}: status of the {instance.GetType().Name} is {status.GetValue( ref instance, Arguments.Empty )}." );
    }
}

public class Order
{
    public string Status { get; private set; } = "New";

    [LogStatus]
    public void Ship()
    {
        this.Status = "Shipped";
        Console.WriteLine( "Order shipped." );
    }
}

public static class Program
{
    public static void Main()
    {
        new Order().Ship();
    }
}
Ship: status of the Order is New.
Order shipped.

See Also

Reference

ImportMemberAttribute
Property<TValue>
Event<TDelegate>
ILocationBinding<T>
IInstanceScopedAspect

Other Resources

Advice Parameters
Understanding Aspect Lifetime and Scope