| 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
- Import the property as an ILocationBinding<T>, which reads and writes the property of the object passed to its methods, typically received by a
[This]parameter. It works in any advice. To read the value only, a parameter of the type of the property also works. - Make the aspect instance-scoped by implementing IInstanceScopedAspect, and make the advice an instance method. See Understanding Aspect Lifetime and Scope.
- For an event in an InstanceLevelAspect, import the event into an Event<TDelegate> field of the aspect instead.
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