| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The aspect '<AspectType>' cannot introduce member '<Member>' into type '<TargetType>' because it is already defined in type '<DeclaringType>'. Use a different OverrideStrategy or skip the member. |
Cause
When an aspect introduces a member, such as a method, property, field, event, indexer, constructor or finalizer, Metalama first checks whether the target type, or one of its visible base types, already defines a member with the same name, or the same signature for methods. What happens then depends on the OverrideStrategy of the advice. The default strategy, Fail, reports LAMA0500 and doesn't introduce the member.
In the message, <Member> is the member that the aspect tries to introduce, <TargetType> is the target type, and <DeclaringType> is the type that already defines the member: the target type itself or one of its base types.
In the following example, the Resettable aspect introduces a Reset method into the ShoppingCart class, but the class already has a Reset method.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0500.Error;
5
6public class ResettableAttribute : TypeAspect
7{
8 [Introduce]
9 public void Reset()
10 {
11 Console.WriteLine( "Resetting the object." );
12 meta.Proceed();
13 }
14}
15
1using System.Collections.Generic;
2
3namespace Doc.LAMA0500.Error;
4
5// Error: the aspect introduces a Reset method, which ShoppingCart already defines.
6[Resettable]
Error LAMA0500: The aspect 'Resettable' cannot introduce member 'ShoppingCart.Reset()' into type 'ShoppingCart' because it is already defined in type 'ShoppingCart'. Use a different OverrideStrategy or skip the member.
7internal partial class ShoppingCart
8{
9 private readonly List<string> _items = new();
10
11 public void Add( string item ) => this._items.Add( item );
12
13 public void Reset() => this._items.Clear();
14}
15
Resolution
Decide what should happen when the member already exists, and specify the override strategy. For declarative advice, set the WhenExists property of the [Introduce] attribute. For programmatic advice, pass the whenExists parameter of the advice method.
- OverrideStrategy.Override overrides the existing member. If it's defined in the target type, the template replaces its implementation and can call the original implementation with meta.Proceed(). If it's defined in a base type, it must be
virtualorabstract, and the aspect introduces anoverridemember. - OverrideStrategy.Ignore keeps the existing member and skips the introduction.
- OverrideStrategy.New introduces a member with the
newmodifier. It's only possible when the existing member is defined in a base type.
Alternatively, rename the introduced member or the existing member to remove the conflict.
In the following example, the aspect uses OverrideStrategy.Override, so it adds its logic to the existing Reset method.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0500.Fixed;
5
6public class ResettableAttribute : TypeAspect
7{
8 [Introduce( WhenExists = OverrideStrategy.Override )]
9 public void Reset()
10 {
11 Console.WriteLine( "Resetting the object." );
12 meta.Proceed();
13 }
14}
15
1using System.Collections.Generic;
2
3namespace Doc.LAMA0500.Fixed;
4
5// Fixed: the aspect overrides the existing Reset method.
6[Resettable]
7internal partial class ShoppingCart
8{
9 private readonly List<string> _items = new();
10
11 public void Add( string item ) => this._items.Add( item );
12
13 public void Reset() => this._items.Clear();
14}
15
1using System;
2using System.Collections.Generic;
3
4namespace Doc.LAMA0500.Fixed;
5
6// Fixed: the aspect overrides the existing Reset method.
7[Resettable]
8internal partial class ShoppingCart
9{
10 private readonly List<string> _items = new();
11
12 public void Add(string item) => this._items.Add(item);
13
14 public void Reset()
15 {
16 Console.WriteLine("Resetting the object.");
17 this._items.Clear();
18 }
19}
20