Open sandboxFocusImprove this doc

LA0016: Composition Aspect Applied to an Interface

Severity Error
Reported by PostSharp
Message Cannot apply a CompositionAspect (<Aspect>) to an interface (<Interface>).

Cause

A CompositionAspect makes its target type implement one or more interfaces, and delegates their members to an implementation object that the aspect creates at run time. Only a class or a struct can hold this implementation, so PostSharp reports LA0016 when the target of the aspect is an interface.

Multicasting does not apply a CompositionAspect to interfaces, because the aspect targets only classes and structs. The message usually comes from an aspect that adds the composition aspect programmatically with IAspectProvider, without excluding interfaces from its targets. <Aspect> is the composition aspect, and <Interface> the interface that received it.

In the following example, the [TaggableModel] aspect provides the [Taggable] composition aspect to every type it is applied to, and it is applied to the IDocument interface.

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

namespace Errors.LA0016_Error;

public interface ITaggable
{
    IList<string> Tags { get; }
}

public class TagList : ITaggable
{
    public IList<string> Tags { get; } = new List<string>();
}

// Implements ITaggable in the target type, delegating to a TagList.
[PSerializable]
public class TaggableAttribute : CompositionAspect
{
    protected override Type[] GetPublicInterfaces( Type targetType ) => new[] { typeof(ITaggable) };

    public override object CreateImplementationObject( AdviceArgs args ) => new TagList();
}

// Makes every type of the model taggable.
[PSerializable]
public class TaggableModelAttribute : TypeLevelAspect, IAspectProvider
{
    // The aspect provides the composition aspect to interfaces too.
    public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
    {
        yield return new AspectInstance( targetElement, new TaggableAttribute() );
    }
}

// TaggableModel provides the composition aspect to this interface.
[TaggableModel]
public interface IDocument
{
    string Title { get; }
}

[TaggableModel]
public class Invoice : IDocument
{
    public string Title => "Invoice 2026-001";
}

public static class Program
{
    public static void Main()
    {
        ITaggable invoice = (ITaggable) new Invoice();
        invoice.Tags.Add( "paid" );
        Console.WriteLine( string.Join( ", ", invoice.Tags ) );
    }
}
error LA0016: LA0016_Error.cs(40,18): Cannot apply a CompositionAspect (Errors.LA0016_Error.TaggableAttribute) to an interface (Errors.LA0016_Error.IDocument).

Resolution

  • In an IAspectProvider, provide the composition aspect only to the types that are not interfaces, for example by testing IsInterface.
  • When you apply the aspect yourself, apply it to the classes that implement the interface instead of the interface.

In the following example, [TaggableModel] skips interfaces, so only the Invoice class implements ITaggable.

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

namespace Errors.LA0016_Fixed;

public interface ITaggable
{
    IList<string> Tags { get; }
}

public class TagList : ITaggable
{
    public IList<string> Tags { get; } = new List<string>();
}

// Implements ITaggable in the target type, delegating to a TagList.
[PSerializable]
public class TaggableAttribute : CompositionAspect
{
    protected override Type[] GetPublicInterfaces( Type targetType ) => new[] { typeof(ITaggable) };

    public override object CreateImplementationObject( AdviceArgs args ) => new TagList();
}

// Makes every type of the model taggable.
[PSerializable]
public class TaggableModelAttribute : TypeLevelAspect, IAspectProvider
{
    // The aspect provides the composition aspect to classes and structs only.
    public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
    {
        if ( !((Type) targetElement).IsInterface )
        {
            yield return new AspectInstance( targetElement, new TaggableAttribute() );
        }
    }
}

[TaggableModel]
public interface IDocument
{
    string Title { get; }
}

[TaggableModel]
public class Invoice : IDocument
{
    public string Title => "Invoice 2026-001";
}

public static class Program
{
    public static void Main()
    {
        ITaggable invoice = (ITaggable) new Invoice();
        invoice.Tags.Add( "paid" );
        Console.WriteLine( string.Join( ", ", invoice.Tags ) );
    }
}

See Also

Reference

CompositionAspect
IAspectProvider

Other Resources

interface-introduction
Adding Aspects Programmatically Using IAspectProvider