| Severity | Error |
| Reported by | Metalama.Framework |
| Message | The dynamic expression '<Expression>' must be explicitly cast to 'IExpression' because it is a dynamic argument of a compile-time method that does not return a dynamic type. |
Cause
Some compile-time methods of the Metalama API have a parameter of type dynamic, which accepts a run-time expression. A typical example is WithObject, which you call on a field, property, or method of the code model to choose the object on which the member is accessed. These methods return a compile-time object, for example an invoker, not a run-time value.
When you pass a dynamic expression, such as the Value property of a parameter, to such a parameter, the template compiler must convert the run-time expression into a compile-time IExpression object. Metalama requires you to make this conversion explicit and reports LAMA0256 when it's implicit. The diagnostic isn't reported when the call is used as a statement on its own.
In the following example, the aspect passes parameter.Value, a dynamic expression, to WithObject.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0256.Error;
6
7public class LogPropertiesAttribute : OverrideMethodAspect
8{
9 public override dynamic? OverrideMethod()
10 {
11 var parameter = meta.Target.Parameters[0];
12
13 foreach ( var property in ((INamedType) parameter.Type).Properties )
14 {
15 // Error: the dynamic expression is passed to the compile-time method WithObject.
Error LAMA0256: The dynamic expression 'parameter.Value' must be explicitly cast to 'IExpression' because it is a dynamic argument of a compile-time method that does not return a dynamic type.
16 var value = property.WithObject( parameter.Value ).Value;
17 Console.WriteLine( $"{property.Name} = {value}" );
18 }
19
20 return meta.Proceed();
21 }
22}
23
1namespace Doc.LAMA0256.Error;
2
3internal class Customer
4{
5 public string? Name { get; set; }
6
7 public string? Email { get; set; }
8}
9
10internal class CustomerService
11{
12 [LogProperties]
13 public void Save( Customer customer ) { }
14}
15
Resolution
Do one of the following:
- Cast the
dynamicexpression to IExpression, as shown in the following example. - If you already have an object that implements IExpression, like the IParameter itself, pass this object directly instead of its Value property.
1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0256.Fixed;
6
7public class LogPropertiesAttribute : OverrideMethodAspect
8{
9 public override dynamic? OverrideMethod()
10 {
11 var parameter = meta.Target.Parameters[0];
12
13 foreach ( var property in ((INamedType) parameter.Type).Properties )
14 {
15 // Fixed: the dynamic expression is explicitly cast to IExpression.
16 var value = property.WithObject( (IExpression) parameter.Value! ).Value;
17 Console.WriteLine( $"{property.Name} = {value}" );
18 }
19
20 return meta.Proceed();
21 }
22}
23
1namespace Doc.LAMA0256.Fixed;
2
3internal class Customer
4{
5 public string? Name { get; set; }
6
7 public string? Email { get; set; }
8}
9
10internal class CustomerService
11{
12 [LogProperties]
13 public void Save( Customer customer ) { }
14}
15
1using System;
2
3namespace Doc.LAMA0256.Fixed;
4
5internal class Customer
6{
7 public string? Name { get; set; }
8
9 public string? Email { get; set; }
10}
11
12internal class CustomerService
13{
14 [LogProperties]
15 public void Save(Customer customer)
16 {
17 var value = customer.Name;
18 Console.WriteLine($"Name = {value}");
19 var value_1 = customer.Email;
20 Console.WriteLine($"Email = {value_1}");
21 }
22}
23