| Severity | Error |
| Reported by | Metalama.Extensions.Interceptors |
| Message | The template '<Template>' cannot implement the interceptor method for the <Site> because <Reason>. The call site is left unchanged. |
Cause
An interceptor redirects the calls to a method to another method that Metalama generates, typically from an aspect template that you select with RedirectToSynthesizedMethod. Metalama derives the signature of the generated method from the intercepted method, and the Configure delegate can adjust it, for instance by adding a parameter.
Metalama reports LAMA1016 when it can't build the generated method from the template, and it leaves the call site unchanged. The <Reason> placeholder gives the cause. The most common ones are:
- An added parameter has no value: the
Configuredelegate calledAddParameter, butWithArgshas no property with the same name andSetArgumentwasn't called for it. - The value of an added parameter can't be written as a constant, for instance a
DateTime. - An added parameter has the name of a parameter of the intercepted method, or isn't passed by value.
- A property of
WithArgsis neither a parameter of the template nor an added parameter. - The template has a run-time parameter that the intercepted method doesn't have and that
WithArgsdoesn't provide, or the template provider has no template with the requested name.
In the following example, the Configure delegate adds a parameter named line, but nothing gives its value at the call site.
1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Aspects;
3using Metalama.Framework.Code;
4using System;
5
6namespace Doc.LAMA1016.Error;
7
8public class InterceptPrintAttribute : TypeAspect
9{
10 public override void BuildAspect( IAspectBuilder<INamedType> builder )
11 => builder.InterceptMethods(
12 i => i
13 .Type( typeof(Printer) ).Methods( "Print" )
14 .RedirectToSynthesizedMethod( nameof(this.Intercept) )
15 .PlaceInCallingType()
16 .Configure( b =>
17 {
18 // Error: no value is given for this added parameter.
19 b.Method.AddParameter( "line", typeof(int) );
20 } ) );
21
22 [Template]
23 public dynamic? Intercept()
24 {
25 Console.Write( $"[line {meta.Target.Parameters["line"].Value}] " );
26
27 return meta.Proceed();
28 }
29}
30
1using System;
2
3namespace Doc.LAMA1016.Error;
4
5public static class Printer
6{
7 public static void Print( string value ) => Console.WriteLine( value );
8}
9
10[InterceptPrint]
11public static class Report
12{
Error LAMA1016: The template 'Intercept' cannot implement the interceptor method for the call to 'Printer.Print(string)' because the added parameter 'line' has no value, because args has no property of this name and the SetArgument method was not called for it. The call site is left unchanged.
13 public static void Run() => Printer.Print( "Hello" );
14}
15
Resolution
Read the reason in the message, and change the aspect so that the template and the generated method agree:
- Give a value to every added parameter, either with a property of
WithArgsthat has the same name or withSetArgument. The value must be a constant. - Rename the added parameter if it conflicts with a parameter of the intercepted method.
- Remove the
WithArgsproperties that match no parameter, and declare in the template every run-time parameter it needs.
In the following example, WithArgs gives the value of the added parameter.
1using Metalama.Extensions.Interceptors;
2using Metalama.Framework.Aspects;
3using Metalama.Framework.Code;
4using System;
5
6namespace Doc.LAMA1016.Fixed;
7
8public class InterceptPrintAttribute : TypeAspect
9{
10 public override void BuildAspect( IAspectBuilder<INamedType> builder )
11 => builder.InterceptMethods(
12 i => i
13 .Type( typeof(Printer) ).Methods( "Print" )
14 .RedirectToSynthesizedMethod( nameof(this.Intercept) )
15 // Fixed: args gives the value of the added parameter.
16 .WithArgs( new { line = 42 } )
17 .PlaceInCallingType()
18 .Configure( b =>
19 {
20 b.Method.AddParameter( "line", typeof(int) );
21 } ) );
22
23 [Template]
24 public dynamic? Intercept()
25 {
26 Console.Write( $"[line {meta.Target.Parameters["line"].Value}] " );
27
28 return meta.Proceed();
29 }
30}
31
1using System;
2
3namespace Doc.LAMA1016.Fixed;
4
5public static class Printer
6{
7 public static void Print( string value ) => Console.WriteLine( value );
8}
9
10[InterceptPrint]
11public static class Report
12{
13 public static void Run() => Printer.Print( "Hello" );
14}
15
1using System;
2
3namespace Doc.LAMA1016.Fixed;
4
5public static class Printer
6{
7 public static void Print(string value) => Console.WriteLine(value);
8}
9
10[InterceptPrint]
11public static class Report
12{
13 public static void Run() => Printer_Print_Interceptor(value: "Hello", line: 42);
14
15 private static void Printer_Print_Interceptor(string value, int line)
16 {
17 Console.Write($"[line {line}] ");
18 Printer.Print(value);
19 }
20}
21