Click here to Skip to main content
15,902,198 members
Articles / Programming Languages / C#
Tip/Trick

How to Use AOP in C# with NConcern .NET

Rate me:
Please Sign up or sign in to vote.
4.52/5 (10 votes)
29 Dec 2016CPOL4 min read 23.4K   7   5
A simple library can allow you to introduce Aspect-Oriented Programming without any difficulty

Introduction

Most AOP frameworks require compromises due to technical limitations (changes needed in the source code, changes in the compilation or deployment process). Few of them are simple to handle and the coupling with the framework is often too strong. This is one of the reasons why too few people are interested in aspect-oriented programming. However, the application of the concepts of aspect-oriented programming is very simple provided they are well understood and have the right tools. This is why I would like to share with you a basic AOP scenario using NConcern .NET, a dedicated open source framework (under MIT licence): https://github.com/Virtuoze/NConcern.

Background

The principle of Aspect-Oriented Programming consists firstly in factorizing the transerve source code in order to maintain it and to make it evolve easily without impacting the business code and, on the other hand, to remove it from the business code to improve readability.

The simplest scenario to understand is to log method calls into console. The goal is to write the business code without worrying about cross-cutting concerns (logging in this scenario). The integration between the business code and the logging aspect is then carried out using the AOP framework.

Business

For our scenario, here is a very simple code that represents a basic calculator:

C#
static public class Calculator
{
    static public int Add(int a, int b)
    {
        return a + b;
    }
}

The calculator just has an "Add" static method to do an integer addition.

Program

Here is a simple usage of calculator in a console application:

C#
static public class Program
{
    static public void Main(string[] args)
    {
        Calculator.Add(2, 3);
    }
}

The method call is not logged into console and if we want to log the method call into console. It is normally necessary (without an AOP Framework) to add the statement directly in the method to do it explicitly as below:

C#
static public class Calculator
{
    static public int Add(int a, int b)
    {
        try
        {
            return a + b;
        }
        finally
        {
            Console.WriteLine(string.Format("You called {0} method.", 
                                             MethodBase.GetCurrentMethod().Name));
        }
    }
}

I use try/finally block to ensure that the log in the console is made even in case of exception handling. MethodBase.GetCurrentMethod() statement is required if we want to rationalize the logging code.

Logging Aspect with NConcern .NET

To use NConcern .NET, you need to reference NConcern.dll assembly. You can download it from:

It's easier to use nuget because it allows you to stay more up-to-date.
On contextual menu of your project, click on "Manage Nuget Packages...".

Image 1

On NuGet Package Manager, fill the search textbox with the keyword NConcern.

Image 2

Install the package by clicking on "install" button.

Image 3

After installation, you can see NConcern as reference.

Image 4

Before logging aspect definition, it is necessary to define the builtin assembly attribute "DebuggableAttribute" to disable method inlining because NConcern is based on method swapping and cannot work when inling optimization is done. Add the debuggable attribute in the "AssemblyInfo.cs" file of target assembly (where business is located) with "IsJITTrackingEnabled" to true and "IsJITOptimizerDisabled" to true too.

Image 5

Now you are ready to create a logging aspect. "NConcern.IAspect" is the interface you need to implement to define an aspect. There is only one method to implement called "Advise" taking a "MethodInfo" as argument and returning an "IEnumerable<Advice>".

The method received as argument is the "target method to advise". The "Advise" method has to return some "Advices". An advice is an additional code to inject into a method to materialized the aspect. In our case, we have to create an advice to log the target method call into console after the target method call itself.

C#
public class Logging
{
    public IEnumerable<Advice> Advise(MethodInfo method)
    {
        yield return Advice.Basic.After(() => Console.WriteLine(string.Format
                                              ("You called {0} method.", method.Name)))
    }
}

Advice can be defined using static methods from "Advice.Basic" (simple delegates), "Advice.Linq" (linq expression) and "Advice.Reflection" (reflection emit). At this stage, logging aspect is able to advise any method by adding a console log after method execution. But nowhere have we specified that the "Add" method of the calculator should be managed by the logging aspect.

Weave logging aspect into "Add" method with the "NConcern.Aspect.Weave<T>(MethodInfo)" method:

C#
static public class Program
{
    static public void Main(string[] args)
    {
        Aspect.Weave<Logging>(typeof(Calculator).GetMethod("Add"));
        Calculator.Add(2, 3);
    }
}

Now when "Add" method is called, a log is done in the console. "NConcern.Aspect.Weave<T>(...)" has some overload to simplify the process. For example, we can weave logging for all methods of Calculator like this:

C#
static public class Program
{
    static public void Main(string[] args)
    {
        Aspect.Weave<Logging>(method => method.DeclaringType == typeof(Calculator));
        Calculator.Add(2, 3);
    }
}

The lifecycle of advices can be controlled with:

  • Aspect.Weave<T>(...): weave an aspect to target method(s)
  • Aspect.Release<T>(...): release aspect for target methods(s)
  • Aspect.Lookup<T>(...): get aspect mapping

You can see that "custom attribute" is not required to implement AOP. However, it can help to discriminate method. If you want to use it to discriminate methods, you have to be carefully about good practice of custom attribute. Indeed, I am used to seeing inadequate use that involves too much coupling. For example, don't create an attribute specialized for an aspect like "LogAttribute". Create an attribute to describe your business like "ServiceAttribute" (to map: logging aspect manage method attributed with "ServiceAttribute"), not to add a dependency.

Conclusion

Implementing Aspect-Oriented Programming in C# can be easy and transparent if you use a good framework. NConcern is a clear, precise and simple implementation without too much compromise. It allows to stay on the initial objective: write the business code without worrying about a cross-cutting concerns because transversal source code can be totally externalized.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
France France
After working in electronics, I fall in love with software development which is a real passion for me, particulary architecture concerns for productivity.

Comments and Discussions

 
QuestionWhen trying to add Aspect to a method that has a variable byref it crashes Pin
Member 1141295917-Apr-18 10:23
Member 1141295917-Apr-18 10:23 
QuestionWhat about disable inlining and JIT Optimization Pin
Francesco Bagnasco31-Dec-16 22:32
Francesco Bagnasco31-Dec-16 22:32 
AnswerRe: What about disable inlining and JIT Optimization Pin
Puresharper2-Jan-17 10:22
professionalPuresharper2-Jan-17 10:22 
AnswerRe: What about disable inlining and JIT Optimization Pin
luxianfeng30-Oct-17 5:49
luxianfeng30-Oct-17 5:49 
GeneralRe: What about disable inlining and JIT Optimization Pin
Puresharper15-Aug-18 13:51
professionalPuresharper15-Aug-18 13:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.