Open sandboxFocusImprove this doc

LAMA0532: An abstract member can't be introduced into a non-abstract type

Severity Error
Reported by Metalama.Framework
Message The aspect '<AspectType>' cannot introduce the abstract member '<Member>' into the type '<TargetType>' because '<TargetType>' is not abstract.

Cause

In C#, only an abstract class can declare abstract members. Metalama enforces the same rule for the members that aspects introduce with methods such as IntroduceMethod, IntroduceProperty, or IntroduceEvent.

Metalama reports LAMA0532 when the build action of the advice, for instance the buildMethod argument of IntroduceMethod, sets the IsAbstract property of the member builder to true and the target type isn't abstract. In the message, <Member> is the introduced member and <TargetType> is the target type.

Templates behave differently: a public template without a body, or a template whose attribute sets IsAbstract, produces an abstract member only when the target type is abstract, and never causes this error.

In the following example, the Validatable aspect introduces an abstract Validate method, but it's applied to a class that isn't abstract.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0532.Error;
5
6public class ValidatableAttribute : TypeAspect
7{
8    public override void BuildAspect( IAspectBuilder<INamedType> builder )
9    {
10        // Derived classes must implement the Validate method.
11        builder.IntroduceMethod( nameof(this.Validate), buildMethod: method => method.IsAbstract = true );
12    }
13
14    // A template without a body introduces a method without a body.
15#pragma warning disable CS0626
16    [Template]
17    public extern void Validate();
18#pragma warning restore CS0626
19}
20
1namespace Doc.LAMA0532.Error;
2
3// Error: the [Validatable] aspect introduces an abstract method, but the class isn't abstract.
4[Validatable]
Error LAMA0532: The aspect 'Validatable' cannot introduce the abstract member 'Entity.Validate()' into the type 'Entity' because 'Entity' is not abstract.

5internal partial class Entity
6{
7    public int Id { get; set; }
8}
9

Resolution

Do one of the following:

  • Make the target type abstract, as in the following example.
  • If the aspect must also support non-abstract types, set IsAbstract only when the target type is abstract, and give the template a body, so that Metalama introduces a regular method into non-abstract types.
  • Restrict the aspect to abstract types with an eligibility condition in its BuildEligibility method.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0532.Fixed;
5
6public class ValidatableAttribute : TypeAspect
7{
8    public override void BuildAspect( IAspectBuilder<INamedType> builder )
9    {
10        // Derived classes must implement the Validate method.
11        builder.IntroduceMethod( nameof(this.Validate), buildMethod: method => method.IsAbstract = true );
12    }
13
14    // A template without a body introduces a method without a body.
15#pragma warning disable CS0626
16    [Template]
17    public extern void Validate();
18#pragma warning restore CS0626
19}
20
Source Code
1namespace Doc.LAMA0532.Fixed;
2
3// Fixed: the class is abstract, so it can receive the abstract method.
4[Validatable]
5internal abstract partial class Entity
6{
7    public int Id { get; set; }
8}
9
Transformed Code
1namespace Doc.LAMA0532.Fixed;
2
3// Fixed: the class is abstract, so it can receive the abstract method.
4[Validatable]
5internal abstract partial class Entity
6{
7    public int Id { get; set; }
8
9    public abstract void Validate();
10}
11

See also