Open sandboxFocusImprove this doc

LAMA0256: The dynamic argument must be cast to IExpression

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 dynamic expression 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
Source Code
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
Transformed Code
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

See also