DEV Community

Cover image for How to Improve .Net Applications with AOP
Daniele Fontani
Daniele Fontani

Posted on • Originally published at levelup.gitconnected.com

How to Improve .Net Applications with AOP

Completing tasks without writing code is the dream of any developer. In this article, we will learn a pattern that makes things happen without writing a line of code. The philosophy is AOP (Aspect-Oriented Programming). This technique is widely used in Java and helps to keep high-quality standards with low effort. Today we will learn how to use it also in .net core project with no pain. After a brief theoric explanation, you will find two examples (all the code is in my GitHub profile).

What is AOP

Let’s start from the Wikipedia definition:

In computing, aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does so by adding additional behavior to existing code (an advice) without modifying the code itself […] This allows behaviors that are not central to the business logic (such as logging) to be added to a program without cluttering the code, core to the functionality. https://en.wikipedia.org/wiki/Aspect-oriented_programming

The concept is simple and can be summarized with one sentence.

** Make things happen without writing code.**

This applies to all the code that is needed but does not introduce any business logic.
Some examples of how AOP can change our code below. The first one is about logging.

public void SaveData(InputClass input)
{
Stopwatch timer= new Stopwatch();
  timer.Start();
  logger.Info("enterd SaveData method");
  if(logger.LogLevel==LoggingLeve.Debug)
  {
      logger.Debug(MyJsonTool.ConvertToJson(input);
  }
dataRepositoryInstance.Save(input);
timer.Start();
 logger.Info($"enterd SaveData method in {timer.ElapsedMilliseconds}ms");
}

What if I tell you that all this code can produce the same output just by writing this?

public virtual void SaveData(InputClass input)
{
  dataRepositoryInstance.Save(input);
}

So, all work just adding a virtual keyword to the method, that’s great! We come back to the virtual keyword later to understand how this is related to AOP.
If you are not convinced by the power of AOP, just see how the code for data fetching can be simplified as follows:

[Fetch("SELECT * FROM customers WHERE name=?")]
public List<MyDTO> GetByName(string name)
{
   return new List<MyDTO>();
}

I hope you are now quite convinced that AOP can help in many scenarios and can be a powerful allied. Let’s see how it works and how to integrate it into a .net core application.

This article contains two examples:

  1. A simple case using DinamyProxy and Autofact that intercept log.
  2. A really nice deep through on AOP techniques that show how to implement an AOP engine.

Example 1: The automatic controller logging

In this sample, we will configure an interceptor to log all incoming requests. This can be extended to all other layers on our application, take it just as a proof of concept.

The interceptor

The interceptor anatomy is very simple. Log it before and after the method execution. In this sample, I use a GUID to reference event logs together, but many improvements can be made.

public class AutofacModule : Module
  {
      protected override void Load(ContainerBuilder builder)
      {

          // Register the inteceptor
          builder.Register(c => new CallLogger())
         .Named<IInterceptor>("log-calls");


          builder.Register(c => new ValuesService(c.Resolve<ILogger<ValuesService>>()))
              .As<IValuesService>()
              .InstancePerLifetimeScope()                
              .EnableInterfaceInterceptors();
      }
  }


  public class CallLogger : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            var executionId = Guid.NewGuid().ToString();

            Debug.WriteLine("{0} - Calling method {1} with parameters {2}... ", 
                executionId,
               invocation.Method.Name,
               JsonConvert.SerializeObject(invocation.Arguments));

            invocation.Proceed();

            Debug.WriteLine("{0} - Done: result was {1}.", 
                executionId, 
               JsonConvert.SerializeObject( invocation.ReturnValue));
        }
    }

We can discuss until tomorrow about how is stupid dumping data into logs, or we can improve this system to use a better logging system and a clever way to trace input, timing, and output.

As you see, there is a trace of method execution, with timing. Image this, out of the box, on all controller of your Asp.net Web API application, or in each service method on the business logic. Nice? It saves tons of lines of code.

Read the full article and learn how the AOP works under the hood

Top comments (0)