| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The aspect '<AspectType>' cannot introduce virtual member '<Member>' because it is also static. |
Cause
In a class or a struct, a static member can't be virtual because virtual members are resolved on an instance. Metalama reports LAMA0507 when an aspect introduces a member that is both static and virtual into a type that isn't an interface. Interfaces are exempt because C# allows static virtual members in interfaces.
The introduced member is static when the introduction scope is IntroductionScope.Static, or when the scope is the default one and the template is static. It's virtual when the template is virtual, when the IsVirtual property of the custom attribute is set, or when the build action sets the IsVirtual property.
In the following example, the Describe aspect introduces the GetDescription method with the static scope, and its build action makes the method virtual.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0507.Error;
5
6public class DescribeAttribute : TypeAspect
7{
8 public override void BuildAspect( IAspectBuilder<INamedType> builder )
9 {
10 // A static member cannot be virtual.
11 builder.IntroduceMethod(
12 nameof(GetDescription),
13 scope: IntroductionScope.Static,
14 buildMethod: method => method.IsVirtual = true );
15 }
16
17 [Template]
18 public string GetDescription()
19 {
20 return meta.Target.Type.Name;
21 }
22}
23
1namespace Doc.LAMA0507.Error;
2
3// Error: the [Describe] aspect introduces a method that is both static and virtual.
4[Describe]
Error LAMA0507: The aspect 'Describe' cannot introduce virtual member 'Product.GetDescription()' because it is also static.
5public partial class Product
6{
7 public string? Name { get; set; }
8}
9
Resolution
Decide whether the introduced member must be static or virtual:
- If derived classes need to override the member, introduce it as an instance member: remove the static scope, or use a non-static template. This is the fix shown in the example below.
- If the member must be static, don't make it virtual: remove the
virtualmodifier from the template, and don't setIsVirtualin the custom attribute or in the build action.
In the following example, the aspect introduces a virtual instance method.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3
4namespace Doc.LAMA0507.Fixed;
5
6public class DescribeAttribute : TypeAspect
7{
8 public override void BuildAspect( IAspectBuilder<INamedType> builder )
9 {
10 // The member is introduced as an instance member, so it can be virtual.
11 builder.IntroduceMethod(
12 nameof(GetDescription),
13 buildMethod: method => method.IsVirtual = true );
14 }
15
16 [Template]
17 public string GetDescription()
18 {
19 return meta.Target.Type.Name;
20 }
21}
22
1namespace Doc.LAMA0507.Fixed;
2
3// Fixed: the [Describe] aspect introduces a virtual instance method.
4[Describe]
5public partial class Product
6{
7 public string? Name { get; set; }
8}
9
1namespace Doc.LAMA0507.Fixed;
2
3// Fixed: the [Describe] aspect introduces a virtual instance method.
4[Describe]
5public partial class Product
6{
7 public string? Name { get; set; }
8
9 public virtual string GetDescription()
10 {
11 return "Product";
12 }
13}
14