Open sandboxFocusImprove this doc

Developing Member-Level Aspects

A member-level aspect is an aspect that applies to one method, field, property or event, and adds behaviors to it. It derives from one of the following classes:

Base class Target Advices
MethodLevelAspect A method or a constructor Method boundary advices, such as OnMethodEntryAdvice, and the method interception advice OnMethodInvokeAdvice
LocationLevelAspect A field, a property, a parameter or a return value OnLocationGetValueAdvice and OnLocationSetValueAdvice for fields and properties, and LocationValidationAdvice
EventLevelAspect An event The event interception advices, such as OnEventAddHandlerAdvice

The behaviors are advice methods of the aspect class (see Advice Methods). Each parameter of an advice method receives a typed value of the target, such as an argument or the return value (see Advice Parameters). The event interception advices and LocationValidationAdvice are the exceptions: they have a fixed signature.

To add behaviors to several members of a type or an assembly with one aspect, see Developing Type- and Assembly-Level Aspects.

Example

The following aspect measures the duration of a method and writes it to the console.

using System;
using System.Diagnostics;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Serialization;

[PSerializable]
public sealed class ProfileAttribute : MethodLevelAspect
{
    [OnMethodEntryAdvice]
    public void OnEntry( [State( StateScope.MethodInvocation )] out Stopwatch stopwatch )
    {
        stopwatch = Stopwatch.StartNew();
    }

    [OnMethodExitAdvice]
    public void OnExit( [DeclarationName( IncludeTypeName = true )] string methodName,
                        [State( StateScope.MethodInvocation )] Stopwatch stopwatch )
    {
        Console.WriteLine( "{0} took {1} ms.", methodName, stopwatch.ElapsedMilliseconds );
    }
}

The aspect is applied as a custom attribute:

public class OrderService
{
    [Profile]
    public void PlaceOrder( Order order )
    {
        // Method body.
    }
}

PostSharp transforms PlaceOrder into code that is equivalent to the following:

public void PlaceOrder( Order order )
{
    Stopwatch stopwatch;
    aspect.OnEntry( out stopwatch );
    try
    {
        // Method body.
    }
    finally
    {
        aspect.OnExit( "OrderService.PlaceOrder", stopwatch );
    }
}

How it works

The example shows the main rules of a member-level aspect:

  • The advices apply to the target of the aspect. They need no pointcut. An advice that cannot apply to this kind of declaration, for instance a location advice in a MethodLevelAspect, causes the error LA0049.
  • The advices of one family, such as the entry and exit advices, form one group and are woven as one transformation: here, one try / finally construct. You do not need to declare the group.
  • The parameters of the advices are bound to values of the target. methodName receives the name of the method, which is a constant. The two stopwatch parameters are bound to the same variable, which lives for one execution of the method: the entry advice assigns it, and the exit advice reads it.
  • No object is allocated on each call, except the Stopwatch itself.

Comparison with simple aspects

A simple aspect, such as OnMethodBoundaryAspect, also applies to one declaration (see Developing Simple Aspects). Its methods receive an AdviceArgs object, such as MethodExecutionArgs. This object is allocated on the heap on each call, and it gives access to the arguments and the return value as object values, which the aspect must cast.

A member-level aspect declares only the values it needs, with their types. PostSharp checks these declarations against each target at build time. To convert a simple aspect into a member-level aspect, see Modernizing Your Custom Aspects.

In this chapter

Section Description
Advice Methods This article explains how to write advice methods, lists the kinds of advices, and describes the properties of the advice attributes.
Advice Parameters This article lists the binding attributes that give an advice the values it needs, such as arguments, the return value, the exception or a variable shared between advices.
Modernizing Your Custom Aspects This article shows how to convert an aspect that receives MethodExecutionArgs, MethodInterceptionArgs or LocationInterceptionArgs into a member-level aspect with bound parameters.

See Also

Reference

MethodLevelAspect
LocationLevelAspect
EventLevelAspect

Other Resources

Developing Simple Aspects
Developing Type- and Assembly-Level Aspects