| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot introduce the interface <Interface> into the type <TargetType> because this type already implements its base interface <BaseInterface>. To keep the existing implementation of <BaseInterface>, set AncestorOverrideAction to Ignore. |
Cause
When an aspect introduces an interface with IntroduceInterfaceAttribute, with an IntroduceInterfaceAdviceInstance or as a CompositionAspect, it also introduces the base interfaces of this interface. When the target type already implements one of these base interfaces, PostSharp follows the AncestorOverrideAction of the introduction. Its default value, Fail, reports LA0005 on the target type.
<BaseInterface> is the base interface that the target type already implements, directly or indirectly. The target type can implement it in its source code, through a base type, or because another aspect introduced it first.
When the target type implements <Interface> itself, PostSharp reports LA0004 instead.
In the following example, the [Describable] aspect introduces IDescribable, which extends INamed, into Customer, which already implements INamed.
using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0005_Error;
public interface INamed
{
string Name { get; }
}
public interface IDescribable : INamed
{
string Describe();
}
[PSerializable]
[IntroduceInterface( typeof(IDescribable) )]
public class DescribableAttribute : InstanceLevelAspect, IDescribable
{
public string Name => this.Instance!.GetType().Name;
public string Describe() => $"Instance of {this.Instance!.GetType().Name}";
}
// The class already implements INamed, which IDescribable extends.
[Describable]
public class Customer : INamed
{
public string Name { get; set; } = "Alice";
}
public static class Program
{
public static void Main()
{
Console.WriteLine( new Customer().Name );
}
}
error LA0005: LA0005_Error.cs(29,14): Cannot introduce the interface Errors.LA0005_Error.IDescribable into the type Errors.LA0005_Error.Customer because this type already implements its base interface Errors.LA0005_Error.INamed. To keep the existing implementation of Errors.LA0005_Error.INamed, set AncestorOverrideAction to Ignore.
Resolution
- Set the AncestorOverrideAction property of the introduction to Ignore: the target type keeps its own implementation of the base interface, and the aspect introduces the other interfaces. A CompositionAspect sets its AncestorOverrideAction property in its constructor.
- Otherwise, remove the base interface from the target type, or introduce an interface that does not extend it.
In the following example, Customer keeps its own Name property, and the aspect introduces the Describe method.
using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;
namespace Errors.LA0005_Fixed;
public interface INamed
{
string Name { get; }
}
public interface IDescribable : INamed
{
string Describe();
}
[PSerializable]
// The class keeps its own implementation of INamed, and the aspect introduces only IDescribable.
[IntroduceInterface( typeof(IDescribable), AncestorOverrideAction = InterfaceOverrideAction.Ignore )]
public class DescribableAttribute : InstanceLevelAspect, IDescribable
{
public string Name => this.Instance!.GetType().Name;
public string Describe() => $"Instance of {this.Instance!.GetType().Name}";
}
[Describable]
public class Customer : INamed
{
public string Name { get; set; } = "Alice";
}
public static class Program
{
public static void Main()
{
var customer = new Customer();
// The interface introduced into Customer is not visible at compile time, so the object is cast at run time.
var describable = (IDescribable) (object) customer;
Console.WriteLine( describable.Name );
Console.WriteLine( describable.Describe() );
}
}
Alice
Instance of Customer
See Also
Reference
IntroduceInterfaceAttribute
InterfaceOverrideAction
CompositionAspect
Other Resources