Open sandboxFocusImprove this doc

LAMA0286: A non-dynamic run-time expression can't be cast to IExpression

Severity Error
Reported by Metalama.Framework
Message Cannot cast the non-dynamic run-time expression '<Expression>' to IExpression. Use ExpressionFactory.Capture.

Cause

The IExpression interface is the compile-time representation of a run-time expression. In a template, casting a dynamic expression to IExpression, for instance (IExpression) meta.Proceed(), is a special syntax that captures the expression. Metalama supports this syntax only for dynamic expressions, which can't be passed to ExpressionFactory.Capture because of a limitation of the C# language.

Metalama reports LAMA0286 when a template casts a run-time expression whose type isn't dynamic to IExpression. The C# cast compiles, but it can't work: the run-time value doesn't exist when the template runs, so it can't be converted to an IExpression object.

In the following example, the aspect casts the run-time local variable startTime, of type object, to IExpression.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using System;
4
5namespace Doc.LAMA0286.Error;
6
7public class LogStartTimeAttribute : OverrideMethodAspect
8{
9    public override dynamic? OverrideMethod()
10    {
11        object startTime = DateTime.Now;
12        IExpression startTimeExpression;
13
14        // Error: 'startTime' is a run-time expression that isn't dynamic, so it can't be cast to IExpression.
        Error LAMA0286: Cannot cast the non-dynamic run-time expression 'startTime' to IExpression. Use ExpressionFactory.Capture.

15        startTimeExpression = (IExpression) startTime;
16
17        Console.WriteLine( $"{meta.Target.Method.Name} started at {startTimeExpression.Value}." );
18
19        return meta.Proceed();
20    }
21}
22
1namespace Doc.LAMA0286.Error;
2
3internal class OrderService
4{
5    [LogStartTime]
6    public void PlaceOrder( string product ) { }
7}
8

Resolution

Call ExpressionFactory.Capture instead of the cast. This method captures the syntax of a run-time expression into an IExpression without evaluating it.

1using Metalama.Framework.Aspects;
2using Metalama.Framework.Code;
3using Metalama.Framework.Code.SyntaxBuilders;
4using System;
5
6namespace Doc.LAMA0286.Fixed;
7
8public class LogStartTimeAttribute : OverrideMethodAspect
9{
10    public override dynamic? OverrideMethod()
11    {
12        object startTime = DateTime.Now;
13        IExpression startTimeExpression;
14
15        // Fixed: ExpressionFactory.Capture creates an IExpression from a run-time expression.
16        startTimeExpression = ExpressionFactory.Capture( startTime );
17
18        Console.WriteLine( $"{meta.Target.Method.Name} started at {startTimeExpression.Value}." );
19
20        return meta.Proceed();
21    }
22}
23
Source Code
1namespace Doc.LAMA0286.Fixed;
2


3internal class OrderService
4{
5    [LogStartTime]
6    public void PlaceOrder( string product ) { }
7}
8
Transformed Code
1using System;
2
3namespace Doc.LAMA0286.Fixed;
4
5internal class OrderService
6{
7    [LogStartTime]
8    public void PlaceOrder(string product)
9    {
10        object startTime = DateTime.Now;
11        Console.WriteLine($"PlaceOrder started at {startTime}.");
12    }
13}
14

See also