| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot use [ImportMember] in aspect "<Aspect>" because the aspect is not instance scoped. |
Cause
An aspect imports a member of its target class with a field annotated with ImportMemberAttribute. PostSharp assigns this field with delegates bound to one object of the target class, so each object needs its own instance of the aspect: the aspect must be instance-scoped.
An aspect is instance-scoped when it implements IInstanceScopedAspect, as InstanceLevelAspect does. Other aspects are static-scoped: a TypeLevelAspect, for example, has a single instance for the whole target class. PostSharp reports LA0079 on the aspect class when a static-scoped aspect has an ImportMemberAttribute field.
In the following example, the [TraceCreation] aspect derives from TypeLevelAspect and imports the Describe method of Customer.
using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0079_Error;
[PSerializable]
// A type-level aspect has one instance for the whole class, so it cannot import members of each object.
public class TraceCreationAttribute : TypeLevelAspect
{
[ImportMember( "Describe", IsRequired = true )]
public Func<string>? Describe;
}
[TraceCreation]
public class Customer
{
public string Name { get; set; } = "Alice";
public string Describe() => $"customer {this.Name}";
}
public static class Program
{
public static void Main()
{
Console.WriteLine( new Customer().Describe() );
}
}
error LA0079: LA0079_Error.cs(10,14): Cannot use [ImportMember] in aspect "Errors.LA0079_Error.TraceCreationAttribute" because the aspect is not instance scoped.
Resolution
Derive the aspect from InstanceLevelAspect, which creates one instance of the aspect for each object of the target class. Use the imported members after PostSharp assigns them, for example in RuntimeInitializeInstance().
using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0079_Fixed;
[PSerializable]
// An instance-level aspect has one instance for each object, which receives the members of this object.
public class TraceCreationAttribute : InstanceLevelAspect
{
[ImportMember( "Describe", IsRequired = true )]
public Func<string>? Describe;
public override void RuntimeInitializeInstance()
{
Console.WriteLine( $"Created {this.Describe!()}" );
}
}
[TraceCreation]
public class Customer
{
public string Name { get; set; } = "Alice";
public string Describe() => $"customer {this.Name}";
}
public static class Program
{
public static void Main()
{
Console.WriteLine( new Customer().Describe() );
}
}
Created customer Alice
customer Alice
See Also
Reference
ImportMemberAttribute
InstanceLevelAspect
TypeLevelAspect
Other Resources