Click here to Skip to main content
15,891,473 members
Articles / Programming Languages / C#

AOP Container

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
19 Sep 2011CPOL11 min read 28.6K   265   17  
Discuss how to add AOP capabilities to IoC containers using a configurable model of Dynamic Decorator
using System;
using System.Collections.Generic;
//using System.Linq;
//using System.Text;

using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;

namespace NCT
{
    public class AspectContext
    {
        public object Target { get; set; }
        public IMethodCallMessage CallCtx { get; set; }
        public AspectContext(object target, IMethodCallMessage callCtx)
        {
            Target = target;
            CallCtx = callCtx;
        }
    }

    public delegate void DecorationDelegate(AspectContext ctx, object[] parameters);

    public class Decoration
    {
        public Decoration(DecorationDelegate aspectHandler, object[] parameters)
        {
            action = aspectHandler;
            paras = parameters;
        }

        public Decoration(DecorationDelegate aspectHandler, object[] parameters, bool bSuppressException)
        {
            action = aspectHandler;
            paras = parameters;
            suppressEx = bSuppressException;
        }

        private DecorationDelegate action;
        private object[] paras;
        private bool suppressEx = false;

        internal DecorationDelegate Action
        {
            get { return action; }
        }

        public object[] Parameters
        {
            get { return paras; }
            set { paras = value; }
        }

        internal bool SuppressException
        {
            get { return suppressEx; }
        }
    }

    public class ObjectProxy : RealProxy, IRemotingTypeInfo
    {
        private object target;
        private Decoration preAspect;
        private Decoration postAspect;
        private String[] arrMethods;

        protected internal ObjectProxy(object target, String[] arrMethods, 
            Decoration preAspect, Decoration postAspect)
            : base(typeof(MarshalByRefObject))
        {
            this.target = target;
            this.preAspect = preAspect;
            this.postAspect = postAspect;
            this.arrMethods = arrMethods;
        }

        public override ObjRef CreateObjRef(System.Type type)
        {
            throw new NotSupportedException("ObjRef for DynamicProxy isn't supported");
        }

        public bool CanCastTo(System.Type toType, object obj)
        {
            return true;
        }

        public string TypeName
        {
            get { throw new System.NotSupportedException("TypeName for DynamicProxy isn't supported"); }
            set { throw new System.NotSupportedException("TypeName for DynamicProxy isn't supported"); }
        }

        public override IMessage Invoke(IMessage message)
        {
            object returnValue = null;
            ReturnMessage returnMessage;

            IMethodCallMessage methodMessage = (IMethodCallMessage)message;
            MethodBase method = methodMessage.MethodBase;

            AspectContext aspCtx = new AspectContext(target, methodMessage);
            // Perform the preprocessing
            if (preAspect != null && HasMethod(method.Name))
            {
                try
                {
                    preAspect.Action(aspCtx, preAspect.Parameters);
                }
                catch (Exception e)
                {
                    if (!preAspect.SuppressException)
                    {
                        returnMessage = new ReturnMessage(e, methodMessage);
                        return returnMessage;
                    }
                }
            }

            // Perform the call
            try
            {
                returnValue = method.Invoke(target, methodMessage.Args);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                    throw ex.InnerException;
                else
                    throw ex;
            }

            // Perform the postprocessing
            if (postAspect != null && HasMethod(method.Name))
            {
                try
                {
                    postAspect.Action(aspCtx, postAspect.Parameters);
                }
                catch (Exception e)
                {
                    if (!postAspect.SuppressException)
                    {
                        returnMessage = new ReturnMessage(e, methodMessage);
                        return returnMessage;
                    }
                }
            }

            // Create the return message (ReturnMessage)
            returnMessage = new ReturnMessage(returnValue, methodMessage.Args, 
                methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage);
            return returnMessage;
        }

        private bool HasMethod(String mtd)
        {
            foreach (string s in arrMethods)
            {
                if (s.Equals(mtd))
                    return true;
            }

            return false;
        }
    }

    public class ObjectProxy<T> : RealProxy, IRemotingTypeInfo
    {
        private object target;
        private Decoration preAspect;
        private Decoration postAspect;
        private String[] arrMethods;

        protected internal ObjectProxy(object target, String[] arrMethods,
            Decoration preAspect, Decoration postAspect)
            : base(typeof(MarshalByRefObject))
        {
            this.target = target;
            this.preAspect = preAspect;
            this.postAspect = postAspect;
            this.arrMethods = arrMethods;
        }

        public override ObjRef CreateObjRef(System.Type type)
        {
            throw new NotSupportedException("ObjRef for DynamicProxy isn't supported");
        }

        public bool CanCastTo(System.Type toType, object obj)
        {
            return target is T && typeof(T)==toType;
        }

        public string TypeName
        {
            get { throw new System.NotSupportedException("TypeName for DynamicProxy isn't supported"); }
            set { throw new System.NotSupportedException("TypeName for DynamicProxy isn't supported"); }
        }

        public override IMessage Invoke(IMessage message)
        {
            object returnValue = null;
            ReturnMessage returnMessage;

            IMethodCallMessage methodMessage = (IMethodCallMessage)message;
            MethodBase method = methodMessage.MethodBase;

            AspectContext aspCtx = new AspectContext(target, methodMessage);
            // Perform the preprocessing
            if (preAspect != null && HasMethod(method.Name))
            {
                try
                {
                    preAspect.Action(aspCtx, preAspect.Parameters);
                }
                catch (Exception e)
                {
                    if (!preAspect.SuppressException)
                    {
                        returnMessage = new ReturnMessage(e, methodMessage);
                        return returnMessage;
                    }
                }
            }

            // Perform the call
            try
            {
                returnValue = method.Invoke(target, methodMessage.Args);
            }
            catch (Exception ex)
            {
                if (ex.InnerException != null)
                    throw ex.InnerException;
                else
                    throw ex;
            }

            // Perform the postprocessing
            if (postAspect != null && HasMethod(method.Name))
            {
                try
                {
                    postAspect.Action(aspCtx, postAspect.Parameters);
                }
                catch (Exception e)
                {
                    if (!postAspect.SuppressException)
                    {
                        returnMessage = new ReturnMessage(e, methodMessage);
                        return returnMessage;
                    }
                }
            }

            // Create the return message (ReturnMessage)
            returnMessage = new ReturnMessage(returnValue, methodMessage.Args,
                methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage);
            return returnMessage;
        }

        private bool HasMethod(String mtd)
        {
            foreach (string s in arrMethods)
            {
                if (s.Equals(mtd))
                    return true;
            }

            return false;
        }
    }

    public class ObjectProxyFactory
    {
        public static object CreateProxy(object target, String[] arrMethods, Decoration preAspect, Decoration postAspect)
        {
            ObjectProxy dp = new ObjectProxy(target, arrMethods, preAspect, postAspect);
            object o = dp.GetTransparentProxy();
            return o;
        }

        public static T CreateProxy<T>(object target, String[] arrMethods, Decoration preAspect, Decoration postAspect)
        {
            ObjectProxy<T> dp = new ObjectProxy<T>(target, arrMethods, preAspect, postAspect);
            object o = dp.GetTransparentProxy();
            return (T)o;
        }

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Object-oriented (OO) is about "classes" not "objects". But I truly believe that "objects" deserve more our attentions. If you agree, read more on... Dynamic Object Programming (DOP), Component-Based Object Extender (CBO Extender), AOP Container and Dynamic Decorator Pattern.

Mobile development is not just another type of front end. The real challenge is actually in the back end: How to present meaningful information in time to mobile users with exponentially increased data flooding around? Here is my first mobile solution: SmartBars - Barcode Reader, Price Comparison and Coupons.

Gary lives in southeast Michigan. My first programming language is FORTRAN. For the last a few years, I have primarily focused on .NET technologies with Mobile Development as my newest interest.

Comments and Discussions