PostSharp4.3//Custom Patterns/Developing Custom Aspects/Developing Simple Aspects/Introducing Interfaces
Introducing Interfaces

When you create a CompositionAspect you are able to dynamically add interfaces to the target code at compile time and make use of that interface type at run time.

  1. The first thing that you need to do is create an aspect that inherits from CompositionAspect and implements its members.

    C#
    [PSerializable] 
    public class GeneralCompose : CompositionAspect 
    { 
        public override object CreateImplementationObject(AdviceArgs args) 
        { 
            throw new System.NotImplementedException(); 
        } 
    }
  2. Next, you need some way to tell the aspect what interface and concrete type you want to implement on the target code. To do that, create a constructor for your aspect that accepts two parameters; one for the interface type and one for the concrete implementation type. Assign those two constructor parameters to field level variables so we can make use of them in the aspect.

    C#
    [PSerializable] 
    public class GeneralCompose : CompositionAspect 
    { 
        private readonly Type _interfaceType; 
        private readonly Type _implementationType; 
    
        public GeneralCompose(Type interfaceType, Type implementationType) 
        { 
            _interfaceType = interfaceType; 
            _implementationType = implementationType; 
        }
  3. There are two methods that you need to implement to complete this aspect. The first is an override of the GetPublicInterfaces(Type) method. This method has a target type parameter which allows you to filter the application of the interface if you choose to. For this example, simply return an array that contains the interface type that was provided via the aspect's constructor.

    C#
     protected override Type[] GetPublicInterfaces(Type targetType) 
    { 
    return new[] { _interfaceType }; 
    }
    Note Note

    The interfaces that are returned from the GetPublicInterfaces(Type) method will be applied to the target code during compilation.

  4. The second method that you need to override is CreateImplementationObject(AdviceArgs). For this example you will return an instance of the concrete implementation that was provided in the aspect's constructor. The CreateImplementationObject(AdviceArgs) method doesn't return the type of the concrete implementation. It returns an instance of that type instead. To create the instance use the CreateInstance(Type, ActivatorSecurityToken) method.

    C#
     public override object CreateImplementationObject(AdviceArgs args) 
    { 
    return Activator.CreateInstance(_implementationType); 
    }
    Note Note

    The CreateImplementationObject(AdviceArgs) method is invoked at the application's runtime.

  5. Now that you have created a complete CompositionAspect, it will need to be applied to the target code. Add the aspect to the target code as an attribute. Provide the attribute with the interface and concrete types that you wish to implement.

    C#
    [GeneralCompose(typeof(IList), typeof(ArrayList))] 
    public class Fruit 
    {  
    }
  6. After compiling your application you will find that the target code now implements the assigned interfaces and exposes itself as a new instance of the concrete type you declared. The next question that needs addressing is how you will interact with the target code using that interface type.

    To access the dynamically applied interface you must make use of a special PostSharp feature. The Cast<SourceType, TargetType>(SourceType) method will allow you to safely cast the target code to the interface type that you dynamically applied. Once that call has been done, you are able to make use of the instance through the interface constructs.

    C#
    [GeneralCompose(typeof(IList), typeof(ArrayList))] 
    public class Fruit 
    { 
        public Fruit() 
        { 
            IList list = Post.Cast<Fruit,IList>(this); 
            list.Add("apple"); 
            list.Add("orange"); 
            list.Add("banana"); 
        } 
    }