| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The template '<Template>' is contained in '<ContainingType>', which is not an aspect, a fabric, or a type implementing ITemplateProvider. |
Cause
Templates, that is, members marked with a template attribute such as [Template] or [Introduce], can only be declared in an aspect, in a fabric, or in a type that implements the ITemplateProvider interface.
Metalama reports LAMA0274 when a template is declared in any other type. The <Template> placeholder is the template and <ContainingType> is the type that contains it. This often happens when you move auxiliary templates to a separate helper class and forget to implement ITemplateProvider, or when the helper class is static, because a static class can't implement an interface.
In the following example, the LogEntry template is declared in the static class LoggingTemplates.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0274.Error;
5
6public class LogAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 LoggingTemplates.LogEntry();
11
12 return meta.Proceed();
13 }
14}
15
16[RunTimeOrCompileTime]
17internal static class LoggingTemplates
18{
19 // Error: LoggingTemplates is not an aspect, a fabric, or an ITemplateProvider.
20 [Template]
Error LAMA0274: The template 'LoggingTemplates.LogEntry()' is contained in 'LoggingTemplates', which is not an aspect, a fabric, or a type implementing ITemplateProvider.
21 public static void LogEntry()
22 {
23 Console.WriteLine( $"Entering {meta.Target.Method}." );
24 }
25}
26
1namespace Doc.LAMA0274.Error;
2
3internal class Calculator
4{
5 [Log]
6 public int Add( int a, int b ) => a + b;
7}
8
Resolution
Do one of the following:
- Make the containing type implement ITemplateProvider. If the type is a static class, remove the
staticmodifier and add aprivateconstructor to prevent instantiation. The templates themselves can remainstatic. - Move the template to the aspect or fabric that uses it.
In the following example, LoggingTemplates implements ITemplateProvider.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0274.Fixed;
5
6public class LogAttribute : OverrideMethodAspect
7{
8 public override dynamic? OverrideMethod()
9 {
10 LoggingTemplates.LogEntry();
11
12 return meta.Proceed();
13 }
14}
15
16// Fixed: the class implements ITemplateProvider. It can't be static, so it has a private constructor instead.
17internal class LoggingTemplates : ITemplateProvider
18{
19 private LoggingTemplates() { }
20
21 [Template]
22 public static void LogEntry()
23 {
24 Console.WriteLine( $"Entering {meta.Target.Method}." );
25 }
26}
27
1namespace Doc.LAMA0274.Fixed;
2
3internal class Calculator
4{
5 [Log]
6 public int Add( int a, int b ) => a + b;
7}
8
1using System;
2
3namespace Doc.LAMA0274.Fixed;
4
5internal class Calculator
6{
7 [Log]
8 public int Add(int a, int b)
9 {
10 Console.WriteLine("Entering Calculator.Add(int, int).");
11 return a + b;
12 }
13}
14