Developing Simple Aspects

In PostSharp, developing an aspect is as simple as deriving a primitive aspect class and overriding some special methods named advice. Aspects encapsulate a transformation of an element of code (such as a method or a property), and advices are the methods that are executed at runtime.

For instance, the effect of the aspect OnMethodBoundaryAspect is to wrap the target method into a try/catch/finally construct, and the advices of this aspect are OnEntry(MethodExecutionArgs), OnSuccess(MethodExecutionArgs), OnException(MethodExecutionArgs) and OnExit(MethodExecutionArgs)

By default, advices of primitive aspect types have an empty implementation, so the aspect has no effect until you override at least one advice.

To develop a simple aspect:

  1. Add PostSharp to your project. See Installing PostSharp Tools for Visual Studio for details.

  2. Create a new class and make it derive from one of the primitive aspect classes (see below).

  3. Annotate the class with the custom attribute PSerializableAttribute. See Understanding Aspect Lifetime and Scope to understand why.

  4. Override one of the aspect advice methods.

Aspect Classes

The following table gives a list of available primitive aspect classes. Every aspect class is described in greater detailed in the class reference documentation.

Aspect Type

Targets

Description

OnMethodBoundaryAspect

Methods

Methods enhanced with an OnMethodBoundaryAspect are wrapped by a try/catch/finally construct. This aspect provides the advices OnEntry(MethodExecutionArgs), OnSuccess(MethodExecutionArgs), OnException(MethodExecutionArgs) and OnExit(MethodExecutionArgs); these advices are invoked directly from the transformed method, the return value, and the exception (if applicable). This aspect is useful to implement tracing or transaction handling, for instance.

For details, see Injecting Behaviors Before and After Method Execution.

OnExceptionAspect

Methods

Methods enhanced with an OnExceptionAspect are wrapped by a try/catch construct. This aspect provides the advice OnException(MethodExecutionArgs); this advice is invoked from the catch block. This aspect is useful to implement exception handling policies. Contrarily to OnMethodBoundaryAspect, this aspect lets you define the type of caught exceptions by overriding the method GetExceptionType(MethodBase)

For details, see Handling Exceptions.

MethodInterceptionAspect

Methods

When a method is enhanced by a MethodInterceptionAspect, all calls to this method are replaced by calls to OnInvoke(MethodInterceptionArgs), the only advice of this aspect type. This aspect is useful when the execution of target method can be deferred (asynchronous calls), must be dispatched on a different thread.

For details, see Intercepting Methods.

LocationInterceptionAspect

Fields, Properties

When a field or a property is enhanced by a LocationInterceptionAspect, all calls to its accessors are replaced by calls to advices OnGetValue(LocationInterceptionArgs) and OnSetValue(LocationInterceptionArgs). Fields are transparently replaced by properties. This aspect is useful to implement functionalities that need to get or set the location value, such as the observability design pattern (INotifyPropertyChanged).

For details, see Intercepting Properties and Fields.

EventInterceptionAspect

Events

When an event is enhanced by an EventInterceptionAspect, all calls to its add and remove semantics are replaced by calls to advices OnAddHandler(EventInterceptionArgs) and OnRemoveHandler(EventInterceptionArgs). Additionally, when the event is fired, even of invoking directly the handlers that were added to the event, the advice OnInvokeHandler(EventInterceptionArgs) is called instead. This aspect is useful to add functionalities to events, such as implementing asynchronous events or materialized list of subscribers.

For details, see Intercepting Events.

CompositionAspect

Types

This aspect introduces an interface into a type by composition. The interface is introduced statically; the aspect method GetPublicInterfaces(Type) should return the type of introduced interfaces. However, the object implementing the interface is created dynamically at runtime by the implementation of the method CreateImplementationObject(AdviceArgs).

For details, see Introducing Interfaces.

CustomAttributeIntroductionAspect

Any

This aspect introduces a custom attribute on any element of code. A custom attribute can be represented as a CustomAttributeData or a ObjectConstruction.

For details, see Introducing Custom Attributes.

ManagedResourceIntroductionAspect

Assemblies

This aspect introduces a managed resource into the current assembly.

For details, see Introducing Managed Resources.

ILocationValidationAspect

Fields, Properties, Parameters

This aspect causes any new value assigned to its target to be validated. If the aspect determines the value is invalid, an exception is thrown. The aspects of the PostSharp.Patterns.Contracts namespace are built on the top of this interface aspect.

For details, see Contracts.

Tip Tip

The implementation of aspects OnMethodBoundaryAspect and OnExceptionAspect is very efficient; they should be preferred over other aspects whenever it makes sense.

Using Aspect Interfaces

The primitive aspect classes listed above only exist for convenience. In reality, PostSharp only understands interfaces. Every of these aspect classes implements a pair of interfaces. For instance, the class OnMethodBoundaryAspect implements the interfaces IOnMethodBoundaryAspect and IMethodLevelAspectBuildSemantics.

The aspect classes are more convenient because they derive from MulticastAttribute, which extends System.Attribute with multicasting capability. See Adding Aspects to Multiple Declarations for details.

If you do not need or want the capabilities of MulticastAttribute (for instance because the aspect is not used as a custom attribute, see IAspectProvider), you can implement the aspect interface manually. An aspect class must implement an interface derived from IAspect, and may implement an interface derived from IAspectBuildSemantics. Please refer to the documentation of the aspect class to get information about the corresponding aspect interface.

Additionally to the aspect interface corresponding to an aspect class, you can define the following interfaces on aspect classes:

Aspect Interface

Description

IAspectProvider

This interface defines a single method ProvideAspects(Object), returning a collection of AspectInstance. The method allows an aspect to dynamically provide other aspects to the weaver.

IInstanceScopedAspect

By default, aspects have static scope: there is one instance of the aspect per target class. Implementing the IInstanceScopedAspect makes the aspect instance-scoped: there will be one instance of this aspect per instance of the target class.