Archive

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:

Compile-Time Weaving

There are basically three ways to modify the behavior of a .NET programs during the build phase:

Source-Level Weaving

You have to parse the source code, modify it and compile it using a standard compiler. The disadvantage is that you have to write a parser-renderer for each of the targeted languages. But you have the possibility to add constructions to the syntax.

Tools:

Writing your own compiler

You can start from scratch or use from an existing open-source compiler like gcc or Mono. The disadvantage is clearly that you have to write your own compiler or extend an existing... and who can afford it? But, at this price, you can do virtually what you want.

Tools:

Modifying the MSIL code

Let the standard compiler do its job, then read the compiled assembly, modify it and write it back. This is the approach of PostSharp.

Tools:

Companion Files

The idea here is to use external files (text files or XML files) to apply aspects on the base code. The weaving can be done at any time using any technique (Compile-Time Weaving or Runtime Weaving). Even if this approach is extremely flexible and reasonably easy for the weaver developer, it may be impractical, in some situations, not to have the possibility to apply aspects to a class in the same source file as this class.

A good example is taken from the Policy Injection application Block of the Enterprise Library:

<policies>
     <add name="Authorize and Audit">
       <matchingRules>
         <add type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.NamespaceMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection" 
              name="Namespace Matching Rule" 
              match="PolicyInjectionQuickStart.BusinessLogic" 
              ignoreCase="false" />
       </matchingRules>
       <handlers>
         <add name="Logging Handler" 
              type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.LogCallHandler, Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers" 
              logBehavior="BeforeAndAfter"
              beforeMessage="Before" 
              afterMessage="After" 
              includeParameterValues="true" 
              includeCallTime="true" 
              includeCallStack="false" 
              severity="Information">
           <categories>
             <add name="Audit" />
           </categories>
         </add>
       </handlers>
    </add>
 </policies>

XML companion files may be difficult to read by humans, but they can easily be generated by interactive configuration tool.s

PostSharp can be used as a base to develop such weavers, but the integration with the build process should be customized.