Archive

Extending the Language

The most popular approach so far has been to define extensions to the base language, i.e. a new language based on the language of the aspected code. The de-facto standard in the Java culture is AspectJ. The following example is taken from the AspectJ Programming Guide:

 1 aspect FaultHandler {
 2
 3   private boolean Server.disabled = false;
 4
 5   private void reportFault() {
 6     System.out.println("Failure! Please fix it.");
 7   }
 8
 9   public static void fixServer(Server s) {
10     s.disabled = false;
11   }
12
13   pointcut services(Server s): target(s) && call(public * *(..));
14
15   before(Server s): services(s) {
16     if (s.disabled) throw new DisabledException();
17   }
18
19   after(Server s) throwing (FaultException e): services(s) {
20     s.disabled = true;
21     reportFault();
22   }
23 }

As you can see, lines 3-11 is pure Java but 13-22 use the AspectJ extension. Even if the purpose of this section is not to explain the AspectJ syntax, note the pointcut, before and after keywords.

The advantage of this approach is that the semantics of the language adapted on purpose, so the resulting code is clean and consistent. No 'trick'. A drawback is that this approach is language-dependent, if your aim is to develop a weaver, you have to develop a code enhancer for every targeted language. See the Compile-Time Weaving techniques for details. A weaver developer should also ideally provide integration with the IDE (Intellisense).

It is not possible to write an aspect weaver of this type using PostSharp, because PostSharp supposes that the code has already been compiled. Also, Runtime Weaving techniques are all unadapted for this scenario.

Glossary

Glossary

You will often meet the following terms in AOP literature. I will try to explain in plain English...

Join point:
A location or a 'point' in the program. For instance: the entry or the exit of a method, a field access, ...
Pointcut:
A 'query' that 'selects' join points
Advice:
A piece of code that alters the behavior of the program. Advices are inserted at join points.
Aspect:
The encapsulation of a cross-cutting concern. Typically a set of advices.
Weaving:
The process of injecting advices at join points, i.e. the process of modifying the behavior of the program.

Custom Attributes

This is the approach of PostSharp Laos. Aspects are programmed as custom attributes and normally applied to classes, methods and fields. We gave already an example above. Here is a second. It implements transaction boundaries in Visual Basic .NET (the example was simplified for brievety):

Imports PostSharp.Laos
Imports System.Transactions

 _
Public NotInheritable Class TransactionScopeAttribute
    Inherits OnMethodBoundaryAspect

    Public Overrides Sub OnEntry(
         ByVal eventArgs As PostSharp.Laos.MethodExecutionEventArgs)

        eventArgs.State = New TransactionScope()

    End Sub

    Public Overrides Sub OnExit(
        ByVal eventArgs As PostSharp.Laos.MethodExecutionEventArgs)

        Dim transactionScope As TransactionScope = eventArgs.State

        If eventArgs.Exception Is Nothing Then
            transactionScope.Complete()
        End If

        transactionScope.Dispose()

    End Sub

End Class

Here is how the new custom attribute can be used to make a method transactional:

 _
Sub Transfer(ByVal fromAccount As Account, 
     ByVal toAccount As Account, ByVal amount As Decimal)
  fromAccount.Balance -= amount
  toAccount.Balance += amount
End Sub

One of the problems, when using custom attributes, is that it should normally be applied to each target explicitly. The .NET languages do not offer the possibility to apply custom attributes to a set of code elements. PostSharp Laos solves this issue by defining a 'multicast' mechanism. For instance, the following code applies the TransactionScope attribute to all methods of all types of a namespace: