Develop with Aspects

AOP addresses exception handling, transactions, tracing, and INotityPropertyChanged more elegantly than conventional OOP.

Automate design patterns

Question: what do the following features have in common?

  • Logging
  • Performance Instrumentation
  • Security Auditing
  • Transaction Handling
  • Exception Handling
  • Multithreading
  • Data binding
  • Undo/Redo

Answer: they all pollute business code and require a lot of boilerplate code to implement.


These are implementation patterns and, although it's possible to explain in natural language how to implement them, the conventional object-oriented paradigm does not allow developers to express them formally - which means they must be implemented manually.


This is precisely why aspect-oriented programming was invented.


PostSharp is the most comprehensive framework for aspect-oriented programming in Microsoft .NET and is used in production by thousands of professional software developers every day.


With PostSharp, software developers can encapsulate implementation patterns into classes called aspects, and apply these aspects to their code using custom attributes.

Aspect Primitives

PostSharp provides the following aspect primitives, from which to build your own:

Aspect Primitive Advices Common Use
OnMethodBoundaryAspect OnEntry, OnSuccess, OnException, OnExit Instrumentation, security, validation.
MethodInterceptionAspect OnInvoke Thread dispatching, caching
LocationInterceptionAspect OnGetValue, OnSetValue Undo/Redo, INotifyPropetyChanged, persistence, validation.
EventInterceptionAspect OnAddHandler, OnRemoveHandler, OnInvokeHandler Fault-tolerant events, asynchronous events.  
CustomAttributeIntroductionAspect None (use with IAspectProvider). Complete WCF data contracts, copy attributes from model to view-model.  
ManagedResourceIntroductionAspect None (use with IAspectProvider). Compute stuff at build-time and decrease application startup time.  

For instance, this aspect writes a message before and after the method executions to which it is applied:

[Serializable] public class TraceAttribute : OnMethodBoundaryAspect { public override void OnEntry(MethodExecutionEventArgs args) { Trace.TraceInformation("Entering {0}.", args.Method); } public override void OnExit(MethodExecutionEventArgs args) { Trace.TraceInformation("Leaving {0}.", args.Method); } }

Applying Aspects to Code

PostSharp offers several ways to add aspects to code:

Custom Attributes

By default, aspects are also custom attributes. With PostSharp, you can apply aspects directly to the code you want to enhance:

[Trace] public void CreateCustomer(int id, string name) { /* ... */ }

Multicast Attributes

This feature enables you to add an aspect to a several targets with a single line of code:

[assembly: Trace( AttributeTargetTypes="MyApp.BusinessProcesses.*", AttributeTargetMemberAttributes = AttributeTargetElements.Public )]

Programmatically

When declarative options are not enough, write an IAspectProvider and unleash the full power of System.Reflection and LINQ.

[MulticastAttributeUsage(MulticastTargets.Field | MulticastTargets.Property, TargetMemberAttributes = MulticastAttributes.Public | MulticastAttributes.Instance)] public sealed class AddXmlIgnoreAttribute : MethodLevelAspect, IAspectProvider { private static readonly CustomAttributeIntroductionAspect customAttributeIntroductionAspect = new CustomAttributeIntroductionAspect( new ObjectConstruction(typeof(XmlIgnoreAttribute).GetConstructor(Type.EmptyTypes))); public IEnumerable<AspectInstance> ProvideAspects(object targetElement) { MemberInfo memberInfo = (MemberInfo)targetElement; if (memberInfo.IsDefined(typeof(XmlElementAttribute), false) || memberInfo.IsDefined(typeof(XmlAttributeAttribute), false)) yield break; yield return new AspectInstance(targetElement, customAttributeIntroductionAspect); } }

Aspect Inheritance

Apply aspects automatically to all types or methods derived from the initial target of the aspect. This works with classes, interfaces, abstract methods, virtual methods, and interface methods.

[NotifyPropertyChanged(AttributeInheritance = MulticastInheritance.Strict)] public abstract class Entity { }

Build-Time Initialization

PostSharp instantiates and initializes aspects at build time, then serializes and stores them as a managed resource in the transformed assembly. Aspects are deserialized and executed at run time, leaving the expensive work until build time, which means applications start faster.

Composite Aspects

Sometimes patterns can't be described as a single primitive transformation. Composite aspects allow for the development of more complex patterns made of several transformations.

Composite aspects include the following features:

Feature Description
Advices An advice is a method that adds a behavior to an existing element of code (see above, aspect primitives).
Pointcut A pointcut is an expression (declarative or imperative) that returns the set of code elements to which an advice should be applied.
Member Introduction Add methods, properties or events to the target class.
Interface Introduction Make the target class introduce a new interface.
Member Import Access non-public methods, properties or events from the aspect.