Custom Attributes
This is the approach of PostSharp. 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 <Serializable> 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:
<TransactionScope> 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 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:
<assembly: TransactionScope(TargetTypes="MyNamespace.*")>
