Open sandboxFocusImprove this doc

LAMA0036: A template of the base class has the same name

Severity Error
Reported by Metalama.Framework
Message The class '<ClassName>' defines a new template named '<TemplateName>', but the base class '<BaseClassName>' already defines a template of the same name. Rename the template, or make the template of the base class virtual and override it.

Cause

Advice methods such as Override or IntroduceMethod identify templates by their name. Therefore, all templates of an aspect class, including the templates inherited from its base classes, must have different names.

Metalama reports LAMA0036 when a class derived from an aspect class defines a template that has the same name as a template of a base class, but doesn't override it. This happens, for instance, when the derived class hides the base template with the new modifier. In the message, <TemplateName> is the template name, <ClassName> is the derived class, and <BaseClassName> is its base class.

Metalama reports this error when it loads the aspect class, whether or not the aspect is used.

In the following example, the TimedLog aspect derives from the Log aspect and hides its LogTemplate template with a new one.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0036.Error;
6
7public class LogAttribute : MethodAspect
8{
9    public override void BuildAspect( IAspectBuilder<IMethod> builder )
10    {
11        builder.Override( nameof(this.LogTemplate) );
12    }
13
14    [Template]
15    public dynamic? LogTemplate()
16    {
17        Console.WriteLine( $"Executing {meta.Target.Method}." );
18
19        return meta.Proceed();
20    }
21}
22
23public class TimedLogAttribute : LogAttribute
24{
25    // Error: the base class already defines a template named LogTemplate.
26    [Template]
    Error LAMA0036: The class 'TimedLogAttribute' defines a new template named 'LogTemplate', but the base class 'LogAttribute' already defines a template of the same name. Rename the template, or make the template of the base class virtual and override it.

27    public new dynamic? LogTemplate()
28    {
29        Console.WriteLine( $"{DateTime.Now:T} Executing {meta.Target.Method}." );
30
31        return meta.Proceed();
32    }
33}
34
1namespace Doc.LAMA0036.Error;
2
3internal class Calculator
4{
5    [TimedLog]
6    public int Add( int a, int b ) => a + b;
7}
8

Resolution

Do one of the following:

  • If the derived class should change the behavior of the base template, make the base template virtual and override it in the derived class. Don't add the [Template] attribute to the override: it inherits the attribute of the base method. The following example shows this fix.
  • If both templates are needed, rename the template of the derived class.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0036.Fixed;
6
7public class LogAttribute : MethodAspect
8{
9    public override void BuildAspect( IAspectBuilder<IMethod> builder )
10    {
11        builder.Override( nameof(this.LogTemplate) );
12    }
13
14    [Template]
15    public virtual dynamic? LogTemplate()
16    {
17        Console.WriteLine( $"Executing {meta.Target.Method}." );
18
19        return meta.Proceed();
20    }
21}
22
23public class TimedLogAttribute : LogAttribute
24{
25    // Fixed: the template overrides the virtual template of the base class.
26    public override dynamic? LogTemplate()
27    {
28        Console.WriteLine( $"{DateTime.Now:T} Executing {meta.Target.Method}." );
29
30        return meta.Proceed();
31    }
32}
33
Source Code
1namespace Doc.LAMA0036.Fixed;
2


3internal class Calculator
4{
5    [TimedLog]
6    public int Add( int a, int b ) => a + b;
7}
8
Transformed Code
1using System;
2
3namespace Doc.LAMA0036.Fixed;
4
5internal class Calculator
6{
7    [TimedLog]
8    public int Add(int a, int b)
9    {
10        Console.WriteLine($"{(DateTime.Now):T} Executing Calculator.Add(int, int).");
11        return a + b;
12    }
13}
14

See also