| Severity | Error |
| Reported by | Metalama.Extensions.Interceptors |
| Message | The <Source> returned an invalid result for the <Site>. <Detail> |
Cause
The Metalama.Extensions.Interceptors package lets an aspect or a fabric replace the calls to selected methods with calls to another method, called an interceptor. With RedirectToSynthesizedMethod, Metalama generates the interceptor method from a template. A Configure delegate can adjust the generated method for each call site, for instance by adding parameters and type parameters.
Metalama reports LAMA1014 when the result returned for a call site can't be turned into a valid interceptor. In the message, <Source> is the interceptor and the aspect or fabric that registered it, <Site> describes the call, and <Detail> gives the specific problem. Typical details are:
- the
Configuredelegate adds a type parameter but doesn't give its type argument withSetTypeArgument, or the type argument violates the constraints of the type parameter; - the
Configuredelegate sets a name that isn't a valid identifier; - an added parameter receives a value both from
WithArgsand fromSetArgument; - the delegate changes the type of a parameter that is passed by reference;
- the result applies to a method reference, which interceptors generated from templates don't support in this version;
- the method returned for a registration doesn't exist in the current compilation.
In the following example, the aspect adds the type parameter TValue to the generated interceptor, but doesn't say which type argument to use at each call site.
1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Aspects;
3using Metalama.Framework.Code;
4using System;
5
6namespace Doc.LAMA1014.Error;
7
8public class InterceptLoggingAttribute : TypeAspect
9{
10 public override void BuildAspect( IAspectBuilder<INamedType> builder )
11 => builder.InterceptMethods(
12 i => i
13 .Type( typeof(Logger) )
14 .Methods( "Write" )
15 .RedirectToSynthesizedMethod( nameof(this.Intercept) )
16 .PlaceInCallingType()
17 .Configure(
18 b =>
19 {
20 // The type parameter has no type argument at the call site.
21 b.Method.Parameters[0].Type = b.Method.AddTypeParameter( "TValue" );
22 } ) );
23
24 [Template]
25 public dynamic? Intercept()
26 {
27 Console.WriteLine( "Writing a message." );
28
29 return meta.Proceed();
30 }
31}
32
1using System;
2
3namespace Doc.LAMA1014.Error;
4
5internal static class Logger
6{
7 public static void Write( object message ) => Console.WriteLine( message );
8}
9
10[InterceptLogging]
11internal static class Checkout
12{
Error LAMA1014: The interceptor template 'Intercept' registered by the aspect [InterceptLoggingAttribute] applied to 'Checkout' returned an invalid result for the call to 'Logger.Write(object)'. The type parameter 'TValue' of the interceptor method has no type argument.
13 public static void Run() => Logger.Write( 42 );
14}
15
Resolution
Fix the result according to the detail given in the message. In the following example, the Configure delegate calls SetTypeArgument with the type of the argument at the call site, so the generated interceptor method is generic.
1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Aspects;
3using Metalama.Framework.Code;
4using System;
5
6namespace Doc.LAMA1014.Fixed;
7
8public class InterceptLoggingAttribute : TypeAspect
9{
10 public override void BuildAspect( IAspectBuilder<INamedType> builder )
11 => builder.InterceptMethods(
12 i => i
13 .Type( typeof(Logger) )
14 .Methods( "Write" )
15 .RedirectToSynthesizedMethod( nameof(this.Intercept) )
16 .PlaceInCallingType()
17 .Configure(
18 b =>
19 {
20 var typeParameter = b.Method.AddTypeParameter( "TValue" );
21 b.Method.Parameters[0].Type = typeParameter;
22
23 // The type argument is the type of the argument at the call site.
24 b.SetTypeArgument( typeParameter, b.Context.Arguments[0].Type! );
25 } ) );
26
27 [Template]
28 public dynamic? Intercept()
29 {
30 Console.WriteLine( "Writing a message." );
31
32 return meta.Proceed();
33 }
34}
35
1using System;
2
3namespace Doc.LAMA1014.Fixed;
4
5internal static class Logger
6{
7 public static void Write( object message ) => Console.WriteLine( message );
8}
9
10[InterceptLogging]
11internal static class Checkout
12{
13 public static void Run() => Logger.Write( 42 );
14}
15
1using System;
2
3namespace Doc.LAMA1014.Fixed;
4
5internal static class Logger
6{
7 public static void Write(object message) => Console.WriteLine(message);
8}
9
10[InterceptLogging]
11internal static class Checkout
12{
13 public static void Run() => Logger_Write_Interceptor(message: 42);
14
15 private static void Logger_Write_Interceptor<TValue>(TValue message)
16 {
17 Console.WriteLine("Writing a message.");
18 Logger.Write((object)message);
19 }
20}
21