| Severity | Error |
| Reported by | Metalama.Framework |
| Message | '<Member>' cannot use the 'dynamic' type because it is not a template and its declaring type '<DeclaringType>' is <DeclaringTypeScope>. Only templates and members of run-time-only types can use the 'dynamic' type. |
Cause
In Metalama, the dynamic type has a special meaning: in a template, it represents a run-time value, such as the return value of meta.Proceed(). Outside of templates, compile-time code executes during compilation, where no run-time value exists, so dynamic has no meaning there.
Metalama reports LAMA0238 when a field that isn't a template uses the dynamic type, alone or in a constructed type like dynamic[] or List<dynamic>, and the field belongs to a type that isn't run-time-only, for instance an aspect, a fabric, or a type marked with CompileTimeAttribute. The last placeholder of the message gives the scope of the declaring type, for instance run-time-or-compile-time for an aspect.
In the following example, the Log aspect stores its category in a field of type dynamic.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0238.Error;
5
6public class LogAttribute : OverrideMethodAspect
7{
8 // Error: a field of an aspect cannot be of type dynamic because it is not a template.
Error LAMA0238: 'LogAttribute._category' cannot use the 'dynamic' type because it is not a template and its declaring type 'LogAttribute' is run-time-or-compile-time. Only templates and members of run-time-only types can use the 'dynamic' type.
9 private readonly dynamic _category = "General";
10
11 public override dynamic? OverrideMethod()
12 {
13 Console.WriteLine( $"[{this._category}] Entering {meta.Target.Method}." );
14
15 return meta.Proceed();
16 }
17}
18
1namespace Doc.LAMA0238.Error;
2
3internal class Calculator
4{
5 [Log]
6 public int Add( int a, int b ) => a + b;
7}
8
Resolution
Depending on your intent, do one of the following:
- If the field holds a compile-time value, give it a concrete type. The value can still be used in templates, where Metalama inserts it into the generated code. The following example uses this fix.
- If the field must hold a run-time expression built at compile time, use IExpression instead of
dynamic, and use its Value property in templates. - If you want to introduce the field into the target type, add the IntroduceAttribute attribute, so that the field becomes a template.
1using Metalama.Framework.Aspects;
2using System;
3
4namespace Doc.LAMA0238.Fixed;
5
6public class LogAttribute : OverrideMethodAspect
7{
8 // Fixed: the field has a concrete type, so its value is known at compile time.
9 private readonly string _category = "General";
10
11 public override dynamic? OverrideMethod()
12 {
13 Console.WriteLine( $"[{this._category}] Entering {meta.Target.Method}." );
14
15 return meta.Proceed();
16 }
17}
18
1namespace Doc.LAMA0238.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.LAMA0238.Fixed;
4
5internal class Calculator
6{
7 [Log]
8 public int Add(int a, int b)
9 {
10 Console.WriteLine("[General] Entering Calculator.Add(int, int).");
11 return a + b;
12 }
13}
14