Post­Sharp Documentation / Adding Aspects to Code / Adding Aspects Programmatically using IAspect­Provider

Adding Aspects Programmatically using IAspectProvider

You may have situations where you are looking to implement an aspect as part of a larger pattern. Perhaps you want to add an aspect, implement an interface and dynamically inject some logic into the target code. In those situations, you will want to apply an aspect to the target code and have that aspect then add other aspects to other elements of code.

The theoretical concept can cause some mental gymnastics, so let's take a look at the implementation.

  1. Create an aspect that implements that IAspectProvider interface.

    C#
    public class ProviderAspect : IAspectProvider 
    { 
       public IEnumerable<AspectInstance> ProvideAspects(object targetElement) 
       { 
           throw new System.NotImplementedException(); 
       } 
    }
  2. Cast the target object parameter to the type that will be targeted by this aspect: Assembly, Type, MethodInfo, ConstructorInfo or LocationInfo.

    C#
    public IEnumerable<AspectInstance> ProvideAspects(object targetElement) 
    { 
       Type type = (Type) targetElement; 
    
       throw new NotImplementedException(); 
    }
  3. In the ProvideAspects(Object) method returns an AspectInstance of the aspect type you want, for every target element of code.

    C#
    public IEnumerable<AspectInstance> ProvideAspects(object targetElement) 
    { 
        Type type = (Type)targetElement; 
    
        return type.GetMethods().Select( 
           m => return new AspectInstance(targetElement, new LoggingAspect()) ); 
    
    }

This aspect will now add aspects dynamically at compile time. Use of the IAspectProvider interface and technique is usually reserved for situations where you are trying to implement a larger design pattern. For example, it would be used when implementing an aspect that created the NotifyPropertyChangedAttribute pattern across a large number of locations in your codebase. It is overkill for many of the situations that you will encounter. Use it only for complicated pattern implementation aspects that you will create.

Note Note

To read more about NotifyPropertyChangedAttribute, see Handling Corner Cases.

Note Note

PostSharp does not automatically initialize the aspects provided by IAspectProvider, even if the method CompileTimeInitialize is defined. Any initialization, if necessary, should be done in the ProvideAspects method or in the constructor of provided aspects.

However, these aspects are initialized at run time just like normal aspects using the RunTimeInitialize method.

Creating Graphs of Aspects

It is common that aspects provided by IAspectProvider (children aspects) form a complex object graph. For instance, children aspects may contain a reference to the parent aspect.

An interesting feature of PostSharp is that object graphs instantiated at compile-time are serialized, and can be used at run-time. In other words, if you store in a child aspect a reference to another aspect, you will be able to use this reference at run time.

See Also