Tuesday 30 October 2012

Interception on the fly. Decorator pattern



This entry shows how to implement a elemental  AOP functionality from the scratch. Unity 2.0 provides the so-called interception. Basically, interception changes the class behavior. That is a good tool for architects to be involved in cross-cutting features.  Instead, developers do not become aware about all the extra functionality architects add to their class implementation.
This example is an attempt to develop from the scratch an elemental IoC container implementing a kind of interception.
A common design pattern to implement interception is the called Decorator pattern.  Decorator pattern is based on a class that implements the same interface that the class intercepted does. This Decorator class (we can name it like that) has an instance of the original class as a private member, for instance. Since the Decorator class implements all methods interface defines, applications can use it as if the Decorator class being the original class definition. But it doesn't.
Said that, this example generate on-the –fly a Decorator class that provides extra behavior. 
In the GreetingIoCLibrary.dll there are an interface definition and an elemental class implementing it.
namespace GreetingIoCLibrary
{
    public interface IGreeting
    {
        void greeting();
       
    }
}

namespace GreetingIoCLibrary
{
    public class Greeting: IGreeting
    {
        #region IGreeting Members

        public void greeting()
        {
            Console.WriteLine("Hello");
        }

        #endregion
    }
}

Normally, in order to create an object from this type, the “new” operator is used to create a memory space for the object.
class Program
    {
        static void Main(string[] args)
        {

            IGreeting obj = new Greeting();
            obj.greeting(); } }
The result is the following.
   




The container will intercept the class in order to add an extra message. This is a stupid example but shows the decorator pattern generated on the fly being used in implementing functionality class enhancement.
Several elements take part of this example.

 App.config. The example creates a new section like this.
<greeting>
   
    <greetingAssemblies>
      <greetingAssembly location=""/>
    </greetingAssemblies>

    <greetingSection>
      <greetingInstance name="instance1" interface="GreetingIoCLibrary.IGreeting" class="GreetingIoCLibrary.Greeting" interception="yes"/>
     
    </greetingSection>
   
  </greeting>

I assume that it is clear how this configuration section is created.  The important element is the <greetingInstance> where the class intercepted is declared. Be aware that the instance will be served by the elemental container, and remember that : it is just an example focused on Decorator pattern generated on the fly to alter the class behavior just like Unity 2.0 interception extension does.
The container is used like this example:
class Program
    {
        static void Main(string[] args)
        {
           GreetingContainer container = new GreetingContainer();
            // load the references by processing the greeting section
            container.LoadConfiguration();
            //obtain the instance1 intercepted
            IGreeting greeting = (Greeting)container.ObtainInstance("instance1");
           // execute the enriched method
            greeting.greeting();
           
         }
    }
}

Here, exceptions are not taking into account just to clarify the main purpose of this example.
public class GreetingContainer
    {
      
        private GreetingSymbolTableManager symbolTableManager;
        public GreetingContainer()
        {

            symbolTableManager = new GreetingSymbolTableManager();
        }
        public object ObtainInstance(string name)
        {
            return symbolTableManager.obtainObject(name);
        }

      
        public void LoadConfiguration()
        {
            GreetingConfigurationSection section = (GreetingConfigurationSection)ConfigurationManager.GetSection("greeting");

            symbolTableManager.createSymbolTable(section);
        }
    }
The class container  implements tow important methods.
1) LoadConfiguration:  It simply process the app.config section and fill the symbol table. The symbol table is just the list of instances that container will provided when required.
2) ObtainInstance: this method hand over the class instance requested by name.
The symbol table is implemented by the following class:

namespace GreetingIoCContainer
{
    class GreetingSymbolTableManager
    {
        private Dictionary<string,object> symbolTable ;
        public void createSymbolTable(GreetingConfigurationSection section)
        {
            if (symbolTable==null)
            {
                generateSymbolTable(section);
                   
            }

        }
        private void generateSymbolTable(GreetingConfigurationSection section)
        {
           
            symbolTable = new Dictionary<string, object>();
            object classInstantiated = null;
            for (int index = 0; index < section.GreetingSection.Count; index++)
            {
                Assembly assembly=Assembly.LoadFrom("GreetingIoCLibrary.dll");
                Type type=assembly.GetType(section.GreetingSection[index].Class);
               
                if (section.GreetingSection[index].Interception.CompareTo("yes") == 0)
                {
                    // create instance
                    classInstantiated = Activator.CreateInstance(type);
                   

                }
                else
                {
                    // Create intercepted instance
                    string decorator = GreetingClassGenerator.createClass(section.GreetingSection[index].Interface,
                        type);

                    classInstantiated = createDecoratorInstance(decorator, type.Name);
                    // Decorator instantiation
                }
                // adding instance to symbol table
                symbolTable.Add(section.GreetingSection[index].Name, classInstantiated);
                   
            }
        }
        private object createDecoratorInstance(string decorator,string name)
        {
            CompilerParameters parms = new CompilerParameters();

            parms.GenerateExecutable = false;
            parms.GenerateInMemory = true;
            parms.IncludeDebugInformation = false;
            parms.ReferencedAssemblies.Add("GreetingIoCLibrary.dll");
            parms.ReferencedAssemblies.Add("System.dll");

            CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");
           
           
           
            CompilerResults compilerResult=compiler.CompileAssemblyFromSource(parms, decorator);
           
            return  compilerResult.CompiledAssembly.CreateInstance("Decorador");
          
           

        }
        public object obtainObject(string name)
        {
            object o=symbolTable[name];
            return o;
        }



        }
    }

The most important chuck of code is the following:

GreetingClassGenerator.createClass(section.GreetingSection[index].Interface,
                        type);

                    classInstantiated = createDecoratorInstance(decorator, type.Name);

Here, two important things occurs.The first one is the dynamic creation of the Decorador class and the second the creation of a new instance of this type (Decorador class).

Here you are the GreetingClassGenerator that is in charge of creating the new class dynamically.

public static class GreetingClassGenerator
    {


        private static string classNameInternal = "";
        private static string createMethodList(Type type)
        {
           
            string result = "";
            string methodList ="";
           // Type type = Type.GetType(className);
            // for each method, generates the method and enrich the context
            foreach (MethodInfo method in type.GetMethods())
            {
                if (method.Name.CompareTo("greeting") == 0)
                {
                    GreetingMethodInfo methodInfo = new GreetingMethodInfo(method);
                    methodList += methodInfo.obtainMethod();
                }




            }
            return methodList;

        }
        public static string obtainClassName()
        {
            return classNameInternal;
        }
       public  static string createClass(string interfaceName, Type type)
        {
            string classDefinition = "using System; using GreetingIoCLibrary;    public class " + "Decorador : " + interfaceName;
            classDefinition += "{ " + interfaceName + " objClass = new " + type.Name + "(); public " + "Decorador" + "(){}" + createMethodList(type);
            classDefinition += "}";
            classNameInternal = type.Name + "Decorator";
            return classDefinition;

        }
    }

The instantiation of the new class is as following (you can see it in the previous class called GreetingSymbolTableManager:
CompilerParameters parms = new CompilerParameters();

            parms.GenerateExecutable = false;
            parms.GenerateInMemory = true;
            parms.IncludeDebugInformation = false;
            parms.ReferencedAssemblies.Add("GreetingIoCLibrary.dll");
            parms.ReferencedAssemblies.Add("System.dll");

            CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");
           
           
           
            CompilerResults compilerResult=compiler.CompileAssemblyFromSource(parms, decorator);
           
            return  compilerResult.CompiledAssembly.CreateInstance("Decorador");
          
           

As you can see, when the  container is invoked, the following class is generated on the fly and delivered to the application using the container.
The class generated on the fly is the following:

using System;
using GreetingIoCLibrary;
public class Decorador : GreetingIoCLibrary.IGreeting
{ GreetingIoCLibrary.IGreeting objClass = new Greeting();
    public Decorador() { }
   
    public void greeting() {
        Console.WriteLine("Interception");
        objClass.greeting(); } }

As you can see, extra behavior has been added by implementing the Decorator Pattern.
The result of the execution of a instance of the type Greeting is the following: