Open sandboxFocusImprove this doc

LA0191: Instance-Scoped Aspect Applied to an Interface

Severity Error
Reported by PostSharp
Message Cannot apply the aspect "<Aspect>" to "<Target>": instance-scoped aspects cannot be applied to interfaces or to members of interfaces. Apply the aspect to the classes that implement the interface.

Cause

An instance-scoped aspect, such as an InstanceLevelAspect or an aspect that implements IInstanceScopedAspect, has one instance per instance of its target class. PostSharp stores this aspect instance in a field of the class and initializes it in the constructors. An interface has no instances, fields or constructors, so PostSharp reports LA0191 when an instance-scoped aspect is applied to an interface, or to a member of an interface such as a default interface method.

Multicasting does not apply an InstanceLevelAspect to interfaces, so the message usually comes from an aspect that provides other aspects with IAspectProvider and does not check the kind of its target.

In the following example, the [Tracked] aspect is applied to the IEntity interface and inherited by the classes that implement it. It provides a TrackingAspect to each of its targets, including the interface itself.

using System;
using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Serialization;

namespace Errors.LA0191_Error;

[PSerializable]
public class TrackingAspect : InstanceLevelAspect
{
    public override void RuntimeInitializeInstance()
    {
        Console.WriteLine( $"Tracking a new {this.Instance!.GetType().Name}" );
    }
}

[PSerializable]
[MulticastAttributeUsage( Inheritance = MulticastInheritance.Multicast )]
public class TrackedAttribute : TypeLevelAspect, IAspectProvider
{
    public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
    {
        // The interface receives the instance-level aspect, like the classes that implement it.
        yield return new AspectInstance( targetElement, new TrackingAspect() );
    }
}

[Tracked]
public interface IEntity
{
}

public class Customer : IEntity
{
}

public static class Program
{
    public static void Main()
    {
        _ = new Customer();
    }
}
error LA0191: LA0191_Error.cs(30,18): Cannot apply the aspect "Errors.LA0191_Error.TrackingAspect" to "Errors.LA0191_Error.IEntity": instance-scoped aspects cannot be applied to interfaces or to members of interfaces. Apply the aspect to the classes that implement the interface.

Resolution

Apply the instance-scoped aspect to the classes only:

  • In an aspect provider, skip the interfaces: return no aspect instance when the target type is an interface.
  • When you apply the aspect yourself, apply it to the classes that implement the interface. To reach all of them, apply to the interface an aspect with Multicast inheritance that provides the instance-scoped aspect to the classes.

In the following example, the aspect provider skips the interface, and the Customer class receives the TrackingAspect.

using System;
using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Serialization;

namespace Errors.LA0191_Fixed;

[PSerializable]
public class TrackingAspect : InstanceLevelAspect
{
    public override void RuntimeInitializeInstance()
    {
        Console.WriteLine( $"Tracking a new {this.Instance!.GetType().Name}" );
    }
}

[PSerializable]
[MulticastAttributeUsage( Inheritance = MulticastInheritance.Multicast )]
public class TrackedAttribute : TypeLevelAspect, IAspectProvider
{
    public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
    {
        // Only the classes that implement the interface receive the instance-level aspect.
        if ( ((Type) targetElement).IsInterface )
        {
            yield break;
        }

        yield return new AspectInstance( targetElement, new TrackingAspect() );
    }
}

[Tracked]
public interface IEntity
{
}

public class Customer : IEntity
{
}

public static class Program
{
    public static void Main()
    {
        _ = new Customer();
    }
}
Tracking a new Customer

See Also

Reference

InstanceLevelAspect
IInstanceScopedAspect
IAspectProvider

Other Resources

Adding Aspects Programmatically Using IAspectProvider
Adding Aspects to Derived Classes and Methods Using Attributes