This example is the Hello, world of aspect-oriented programming. We will create an aspect that displays a message when a method starts and completes.
The following example is trivial and useless in practice, but it's a good starting point. On the left, you can see the source code, written by a human and stored in the source repository. On the right, you can see the transformed code generated by Metalama, based on the aspects. This is the code that gets executed at run time. The green code, specifically, is injected by Metalama.
1internal static class Calculator
2{
3 [Log]
4 public static double Add(double a, double b) => a + b;
5}
1using System;
2
3internal static class Calculator
4{
5 [Log]
6 public static double Add(double a, double b) { Console.WriteLine("Method started.");
7 try
8 {
9 double result;
10 result = a + b;Console.WriteLine("Method succeeded.");
11 return (double)result;
12 }
13 catch (Exception e)
14 {
15 Console.WriteLine("Method failed: " + e.Message);
16 throw;
17 }
18 }
19}
Implementation
Let's look at the aspect that generates this code:
1using Metalama.Framework.Aspects;
2
3public class LogAttribute : OverrideMethodAspect
4{
5 public override dynamic? OverrideMethod()
6 {
7 Console.WriteLine("Method started.");
8
9 try
10 {
11 // Invoke the method and stores the return value in a variable.
12 var result = meta.Proceed();
13
14 Console.WriteLine("Method succeeded.");
15
16 return result;
17 }
18 catch (Exception e)
19 {
20 Console.WriteLine("Method failed: " + e.Message);
21
22 throw;
23 }
24 }
25}
This aspect is probably the most basic. It has, however, a few points of interest.
The LogAttribute
class derives from the OverrideMethodAspect abstract class, which,
in turn, derives from the System.Attribute class. This makes LogAttribute
a custom
attribute.
The LogAttribute
class implements the OverrideMethod method.
This method acts as a template. Most of the code in this template is injected into the target method, i.e., the method
to which we add the [Log]
custom attribute.
Inside the OverrideMethod implementation, the call
to meta.Proceed()
has a very special meaning. When the aspect is applied to the target, the call to meta.Proceed()
is replaced by the original implementation, with a few syntactic changes to capture the return value.
To remind you that meta.Proceed()
has a different meaning and configure syntax highlighting in the Metalama Tools for
Visual Studio, the text is colored differently than the rest of the code.