| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The aspect '<AspectType>' cannot implement the interface member '<InterfaceMember>' in the type '<TargetType>' because the type already contains '<ExistingDeclaration>', which has the same signature. Set the WhenExists property of the [InterfaceMember] attribute to Ignore or MakeExplicit, or pass OverrideStrategy.Override to ImplementInterface. |
Cause
When an aspect calls ImplementInterface, Metalama introduces the members of the aspect marked with [InterfaceMember] into the target type. By default, these members are introduced as implicit, public implementations.
An implicit implementation can't be introduced if the target type already contains a member with the same signature. This applies to methods, properties, and events, whether the existing member is declared in the target type or inherited from a base type. What Metalama does in this case depends on the WhenExists property of the [InterfaceMember] attribute. Metalama reports LAMA0514 when this property is:
- Fail, or
- Default (the default value), and the
whenExistsparameter of ImplementInterface isn't OverrideStrategy.Override. This includes OverrideStrategy.Ignore, which only applies when the type already implements the whole interface.
In the message, <InterfaceMember> is the interface member, and <ExistingDeclaration> is the existing member of the target type.
In the following example, the Describable aspect implements IDescribable, but the Order class already has a Describe method.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0514.Error;
5
6public interface IDescribable
7{
8 string Describe();
9}
10
11public class DescribableAttribute : TypeAspect
12{
13 public override void BuildAspect( IAspectBuilder<INamedType> builder )
14 {
15 builder.ImplementInterface( typeof(IDescribable) );
16 }
17
18 // WhenExists is not set, so the advice fails if the target type already has a Describe method.
19 [InterfaceMember]
20 public string Describe() => meta.Target.Type.Name;
21}
22
1namespace Doc.LAMA0514.Error;
2
3[Describable]
Error LAMA0514: The aspect 'Describable' cannot implement the interface member 'IDescribable.Describe()' in the type 'Order' because the type already contains 'Order.Describe()', which has the same signature. Set the WhenExists property of the [InterfaceMember] attribute to Ignore or MakeExplicit, or pass OverrideStrategy.Override to ImplementInterface.
4internal partial class Order
5{
6 public int Id { get; set; }
7
8 // Error: Describe has the same signature as IDescribable.Describe.
9 public string Describe() => $"Order {this.Id}";
10}
11
Resolution
Choose how the aspect should handle the existing member:
- To use the existing member as the implementation of the interface member, set WhenExists to InterfaceMemberOverrideStrategy.Ignore. The following example uses this fix.
- To keep the existing member and introduce the template as an explicit implementation, set
WhenExiststo InterfaceMemberOverrideStrategy.MakeExplicit, or set IsExplicit totrue. - To override the existing member with the template, pass OverrideStrategy.Override to ImplementInterface and leave
WhenExistsat its default value. The existing member must be public, and also virtual if it's inherited from a base class. - Rename or remove the existing member of the target type.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0514.Fixed;
5
6public interface IDescribable
7{
8 string Describe();
9}
10
11public class DescribableAttribute : TypeAspect
12{
13 public override void BuildAspect( IAspectBuilder<INamedType> builder )
14 {
15 builder.ImplementInterface( typeof(IDescribable) );
16 }
17
18 // The existing Describe method of the target type implements the interface member.
19 [InterfaceMember( WhenExists = InterfaceMemberOverrideStrategy.Ignore )]
20 public string Describe() => meta.Target.Type.Name;
21}
22
1namespace Doc.LAMA0514.Fixed;
2
3[Describable]
4internal partial class Order
5{
6 public int Id { get; set; }
7
8 // Fixed: this method implements IDescribable.Describe.
9 public string Describe() => $"Order {this.Id}";
10}
11
1namespace Doc.LAMA0514.Fixed;
2
3[Describable]
4internal partial class Order : IDescribable
5{
6 public int Id { get; set; }
7
8 // Fixed: this method implements IDescribable.Describe.
9 public string Describe() => $"Order {this.Id}";
10}
11