Reference

You can develop an Composition aspect by deriving the custom attribute CompositionAspect or by implementing the interface ICompositionAspect.

Overview

The Composition aspect injects new interfaces into an existing type and defers the implementation of these interfaces to another object that implements them. This object is said to be composed into the target type.

Type composition is often considered as a better alternative to multiple inheritance, since complex types are composed of many easiest ones.

More importantly, the Composition aspect can be used to automatically implement interfaces whose implementation is generally plumbing code, for instance the INotifyPropertyChanged interface. This aspect is very often one of the components of compound aspects.

This aspect has both compile-time semantics and runtime semantics.

At compile-time, methods GetPublicInterface and GetProtectedInterfaces are invoked. The aspect should return the set of interfaces that needs to be implemented. We will talk later about protected interfaces.

At runtime, just after the base constructor of the aspected object has been invoked, the CreateImplementationObject method of the aspect is invoked. This method should provide an implementation of composed interfaces.

Sample

The following aspect injects the IList interface to the class to which it is apply. The implementation of this interface is delegated to the type ArrayList.

          [Serializable]
public class ComposeListAttribute : CompositionAspect
{
   public override Type GetPublicInterface( Type type )
   {
     return typeof(IType);
   }

   public override object CreateImplementationObject(
     InstanceBoundLaosEventArgs eventArgs )
   {
     return new ArrayList();
   }
}

[ComposeList]
class ComposedList { }
        

Casting objects to their composed interfaces

Since the interface is injected after compilation, you cannot use the classic C# or Visual Basic casting operator unless you first downcast the instance to System.Object:

ComposedList composedList = new ComposedList();
IList list = (IList) (object) composedList;

The problem of this construct is that it is unsafe (no compile-time error is emitted if the object does not implement the interface) and it has a useless performance overhead.

For this use case, PostSharp provides the casting method Post.Cast<TSource,TTarget> which is both safe and efficient because it is checked and transformed at compile time.

ComposedList composedList = new ComposedList();
IList list = Post.Cast<ComposedList,IList> composedList;

Accessing the implementation object

It is often useful to get directly the object implementing a composed interface. For instance, when you implement the INotifyPropertyChanged interface using a composition aspect, we need to raise the PropertyChanged event from property setters of the target type. But since we cannot raise this event using the semantics of the INotifyPropertyChanged interface, we need direct access to the implementation object.

If you need access to the implementation object, you have to ask the Composition aspect to generate an implementation accessor. This is done by overriding the GetOptions method and setting the flag GenerateImplementationAccessor. This tells PostSharp to implement another interface in the target type, IComposed<T>, where T is the type of the public interface. The GetImplementation method of this interface gives you access to the implementation object.

Thanks to the SetImplementation method, you can change the implementation object on the fly. This feature is one of the biggest advantages of type composition over traditional type inheritance.

There would be a security break, however, if any type had the right to access the implementation. For this reason, implementation accessors require so-called instance credentials (an object of type InstanceCredentials). Only code that knows the credentials of an instance can access the implementation of a composed interface. Next section will explain how to get these credentials. Before that, let us complete this topic and show how to practically access the implementation object to invoke a method that is not a part of the exposed interface (here the Sort method).

          [ComposeList]
class ComposedList 
{
  public void Sort()
  {
    InstanceCredentials credentials = InstanceCredentials.GetCredentials(this);
    IComposed<IList> composed = Post.Cast<ComposedList,IList>(this);
    ArrayList list = (ArrayList) composed.GetImplementation(credentials);
    list.Sort();
  }
}
        

Getting instance credentials

The objective behind instance credentials is to enforce good encapsulation by preventing external code from accessing implementation details. Only code that is a part of the family of an instance can access implementation details. In that sense, instance credentials achieve a similar goal than the protected C# keyword. The difference is that the notion of 'family' is enlarged: any aspect active on a class is considered to be a part of the family of that class.

A typical example is an aspect implementing INotifyPropertyChanged, where a property setter aspect needs to access the implementation of a composed interface so that it can raise the PropertyChanged event.

There are two ways to get the credentials of an instance:

Note that instance credentials are intended to enforce good reason, but should not be used to enforce security requirements. Instance credentials are actually a random 32-bit value and are relatively easy and cheap to break, even if the caller assembly is partially trusted.

Protected interfaces

You can inject protected interfaces to an existing type by overriding the method GetProtectedInterfaces() of the aspect.

When a type exposes a protected interface, one cannot cast that type to the protected interface without providing instance credentials.

Instead of exposing the protected interface directly, the type implements the interface IProtectedInterface<T>, where T is the protected interface in itself. One can get a reference to the interface (which is actually the implementation object) by calling the GetInterface method. This method requires the instance credentials.

Exposing a protected interface is a cleaner alternative to exposing the implementation object through the IComposed interface, even if the same implementation object is finally returned.

When the composed interface is already implemented

The default behavior of the Composition aspect is to emit an error when the aspect is applied on a type that already implements, even indirectly, the interface to be composed. Sometimes, it is preferable to silently skip the aspect in this case. You can force this behavior by overriding the GetOptions method and setting the flag IgnoreIfAlreadyImplemented.