Aspect-Oriented Programming in the .NET Framework

Understand what AOP is and how it is implemented in .NET. While this article is centered around PostSharp, it is not limited to it. We strive to reference other existing AOP tools when relevant.

What is Aspect-Oriented Programming (AOP)?

Aspect-Oriented Programming (AOP), also known as Aspect-Oriented Software Development (AOSD), is a software development approach that emphasizes the separation of concerns. Separation of concerns is one of the most important principles in software development. It stipulates that the same concern should be addressed in a single unit of code, also known as modularization. In procedural programming, the unit of code is the procedure (or function, or method). In object-oriented programming, the unit of code is the class.

Some concerns cannot be successfully implemented using purely procedural or object-oriented programming. An example of this is code security. If you want to secure objects and methods, you must modify the code of each method. This is why security is referred to as a crosscutting concern, because it crosscuts the unit of modularization of the programming paradigm, in this case, the class.

An aspect is a concern that crosscuts multiple classes and/or methods.

Therefore, AOP is a technique that allows addressing issues that crosscut classes. AOP is frequently used to implement caching, tracing, security, or failure injections.

Example

Suppose we have a large set of business objects and some of their methods need to be secured. The current user is required to have certain roles in order to be granted the permission to execute the method. Using the AOP programming model, instead of modifying each method, you could develop an aspect and 'apply' it to the methods of interest. In the PostSharp Framework, the aspect could look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public sealed class RequiresRoleAttribute : OnMethodBoundaryAspect
{
    string[] roles;
    public string[] Roles
    {
        get { return this.roles; }
        set { this.roles = value; }
    }

    public override void OnEntry(MethodExecutionEventArgs e)
    {
        ((ISecurable)e.Instance).RequireRoles(this.roles);
    }
}

This defines a custom attribute that can be applied to any method. You can use wildcards to apply the aspect to a set of objects and methods:

1
[assembly: RequiresRole(Roles = new string[] { "Delete" }, TargetMethods = "Delete*")]

Of course, there are numerous AOP techniques to achieve the same result. The illustration above is just one of them.

Major AOP Techniques in .NET

Essentially, there are two approaches to altering the behavior of a program in .NET (i.e., to weave a .NET program):

  • Compile-Time Weaving : The program is modified during the build process on the development machine, before deployment.
  • Runtime Weaving : The program is modified during its execution, after deployment.

Expressing the Semantics

We know what we want: to apply additional behaviors to existing code. Now we need to know how to express it. We have to articulate the following facts:

  • What behavior we want to add (advices),
  • Where we want to add it (specification of join points using pointcuts).

The following approaches are available when targeting the .NET Framework:

  • Extending the Language : Create a new .NET language with new constructs.
  • Companion Files : Use external files, such as XML files.
  • Custom Attributes : Use 'standard' .NET custom attributes to annotate the code.
  • Domain-Specific Languages: Utilize a graphical designer to express the semantics, as well as IDE integration to simplify build and debugging experiences.
  • Programmatic Tipping : All previous approaches were declarative. Another alternative is to use standard .NET imperative code to add advices to join points.

External Links