| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The aspect '<AspectType>' cannot implement interface '<InterfaceType>' in the type '<TargetType>' because the type already implements it. To skip or override the existing implementation, set the whenExists parameter of ImplementInterface to OverrideStrategy.Ignore or OverrideStrategy.Override. |
Cause
The ImplementInterface method has a whenExists parameter of type OverrideStrategy, which decides what happens when the target type already implements the interface. Its default value is OverrideStrategy.Fail.
Metalama reports LAMA0512 when the strategy is OverrideStrategy.Fail, explicitly or by default, and the target type already implements the interface, either in its own code or through a base type. The check also covers the base interfaces of the implemented interface, so <InterfaceType> can be one of them.
In the following example, the Describable aspect implements IDescribable with the default strategy, but Product already implements this interface.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0512.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 // The default strategy fails when the type already implements the interface.
16 builder.ImplementInterface( typeof(IDescribable) );
17 }
18
19 [InterfaceMember]
20 public string Describe()
21 {
22 return meta.Target.Type.Name;
23 }
24}
25
1namespace Doc.LAMA0512.Error;
2
3// Error: Product already implements IDescribable.
4[Describable]
Error LAMA0512: The aspect 'Describable' cannot implement interface 'IDescribable' in the type 'Product' because the type already implements it. To skip or override the existing implementation, set the whenExists parameter of ImplementInterface to OverrideStrategy.Ignore or OverrideStrategy.Override.
5internal partial class Product : IDescribable
6{
7 public string Describe() => "A product";
8}
9
10[Describable]
11internal partial class Customer { }
12
Resolution
Pass a whenExists value that matches your intent:
- OverrideStrategy.Ignore skips the types that already implement the interface. The members marked with [InterfaceMember] aren't introduced into these types. This is the most common choice.
- OverrideStrategy.Override implements the interface members with the aspect's templates even if the type already implements the interface.
Alternatively, don't apply the aspect to types that already implement the interface.
In the following example, the aspect passes OverrideStrategy.Ignore: Product keeps its own implementation, and Customer receives the implementation of the aspect.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0512.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 // OverrideStrategy.Ignore skips types that already implement the interface.
16 builder.ImplementInterface( typeof(IDescribable), OverrideStrategy.Ignore );
17 }
18
19 [InterfaceMember]
20 public string Describe()
21 {
22 return meta.Target.Type.Name;
23 }
24}
25
1namespace Doc.LAMA0512.Fixed;
2
3// Fixed: the aspect ignores Product because it already implements IDescribable.
4[Describable]
5internal partial class Product : IDescribable
6{
7 public string Describe() => "A product";
8}
9
10[Describable]
11internal partial class Customer { }
12
1namespace Doc.LAMA0512.Fixed;
2
3// Fixed: the aspect ignores Product because it already implements IDescribable.
4[Describable]
5internal partial class Product : IDescribable
6{
7 public string Describe() => "A product";
8}
9
10[Describable]
11internal partial class Customer : IDescribable
12{
13 public string Describe()
14 {
15 return "Customer";
16 }
17}