Open sandboxFocusImprove this doc

Developing Type- and Assembly-Level Aspects

A type-level aspect applies to a type, and an assembly-level aspect applies to an assembly. One such aspect can transform several members of its target, introduce new members into the target type, and access the existing members of the target type. This kind of aspect implements design patterns that span a whole class, such as INotifyPropertyChanged or a threading model.

The aspect derives from one of the following classes:

Base class Target Aspect instances
TypeLevelAspect A class, a struct or an interface One instance per target type.
InstanceLevelAspect A class that is not static One instance per instance of the target class, so the aspect can have a state for each object (see Understanding Aspect Lifetime and Scope). Introductions and imports of members require this base class.
AssemblyLevelAspect An assembly One instance per assembly. Its advices need a MethodPointcut, and it cannot introduce or import members.

The aspect class contains:

To add behaviors to a single method, field, property or event, a member-level aspect is simpler (see Developing Member-Level Aspects).

Example

The following aspect writes a line to the console whenever an instance property of the target class is set. The pointcut selects the properties, and the advice is generic, so the value is not boxed. Apply it to classes only: on a struct, the instance parameter receives a boxed copy, so the value would be stored in the copy.

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

[PSerializable]
public sealed class TracePropertiesAttribute : TypeLevelAspect
{
    [OnLocationSetValueAdvice,
     MulticastPointcut( Targets = MulticastTargets.Property, Attributes = MulticastAttributes.Instance )]
    public void OnPropertySet<T>( [This] object instance,
                                  [DeclarationName( IncludeTypeName = true )] string propertyName,
                                  [LocationValue] T value,
                                  [Binding] ILocationBinding<T> binding )
    {
        Console.WriteLine( "{0} = {1}", propertyName, value );

        binding.SetValue( instance, value );
    }
}

In this chapter

Section Description
Selecting Members with Pointcuts This article explains how pointcuts select the members to which advices apply, and how advices are grouped into one transformation.
Introducing Interfaces, Methods, Properties and Events into Existing Classes This article shows how to introduce an interface, method, property or event into the target class. The new interface or member is implemented by the aspect itself.
Accessing Members of the Target Class This article shows how to import a member of the target class so that the aspect can invoke it through a delegate. It also explains how member introductions and imports interact.
Adding Aspects Dynamically This article shows how an aspect can add other aspects to declarations that it selects with code.
Providing Advices Dynamically This article shows how an aspect can provide import and introduction advices for each target with code.

See Also

Reference

TypeLevelAspect
InstanceLevelAspect
AssemblyLevelAspect
PostSharp.Aspects.Advices

Other Resources

Developing Member-Level Aspects
Developing Simple Aspects