继上次使用remoting实现了AOP,这次是通过RealProxy和ProxyAttribute实现

相比之前一篇remoting实现的AOP,这次用RealProxy和ProxyAttribute实现的简单许多。


代码如下:

首先是透明代理,该类在运行时会自动根据类的特性去代理其被代理对象

using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Services;
using System.Collections.Generic;

namespace AOPProxy.AOP
{
    public class AOPProxyBase : RealProxy
    {
        private Dictionary<string, MarshalByRefObject> _targetDict = null;
        private Dictionary<string, IAOPInterceptAchieveBase> _aopAchieveDict = new Dictionary<string, IAOPInterceptAchieveBase>();

        private static Dictionary<string, AOPProxyBase> _aopProxy = new Dictionary<string, AOPProxyBase>();

        private AOPProxyBase(Type type, Dictionary<string, MarshalByRefObject> targetDict, Dictionary<string, IAOPInterceptAchieveBase> aopAchieveDict)
            : base(type)
        {
            this._targetDict = targetDict;
            this._aopAchieveDict = aopAchieveDict;
        }

        public static AOPProxyBase GetBaseProxyInstance(Type type, Dictionary<string, MarshalByRefObject> targetDict, Dictionary<string, IAOPInterceptAchieveBase> aopAchieveDict)
        {
            string typeName = type.FullName;
            if (_aopProxy.ContainsKey(typeName)==false)
            {
                _aopProxy.Add(typeName, new AOPProxyBase(type, targetDict, aopAchieveDict));

            }
            return _aopProxy[typeName];

        }

        //对应添加了AOPProxy特性的类,系统会自动调用该方法
        public override IMessage Invoke(IMessage msg)
        {
            string targetTypeName = Convert.ToString(msg.Properties["__TypeName"]).Split(',')[0];

            IMethodReturnMessage result = null;
            bool isAOP = false;//是否需要AOP拦截
            
            //构造函数,只有ContextBoundObject(Inherit from MarshalByRefObject)对象才能截获构造函数
            if (msg is IConstructionCallMessage)
            {
                IConstructionCallMessage cusMethod = msg as IConstructionCallMessage;
                RealProxy defaultProxy = RemotingServices.GetRealProxy(_targetDict[targetTypeName]);

                //如果不做下面这一步,_targetDict[targetTypeName]还是一个没有直正实例化被代理对象的透明代理,
                //这样的话,会导致没有直正构建对象。
                defaultProxy.InitializeServerObject(cusMethod);

                //本类是一个RealProxy,它可通过GetTransparentProxy函数得到透明代理
                result = EnterpriseServicesHelper.CreateConstructionReturnMessage(cusMethod, (MarshalByRefObject)GetTransparentProxy());
            }
            else if (msg is IMethodCallMessage)
            {
                IMethodCallMessage method = (IMethodCallMessage)msg;
                AOPMethodBaseAttribute aopMethod = null;

                //查询目标方法是否使用了启用AOP的AOPMethodAttribute
                foreach (Attribute attr in method.MethodBase.GetCustomAttributes(false))
                {
                    if (attr is AOPMethodBaseAttribute)
                    {
                        aopMethod = attr as AOPMethodBaseAttribute;
                        isAOP = true;
                        break;
                    }
                }

                if (isAOP)//需要AOP拦截
                {

                    if (aopMethod.AopLocation == AOPLocation.Before)
                    {
                        bool check = _aopAchieveDict[aopMethod.NameSpaceClass].BeforeAchieve(method);
                        if (check)
                        {
                            result = RemotingServices.ExecuteMessage(_targetDict[targetTypeName], method);
                        }
                    }
                    else if(aopMethod.AopLocation == AOPLocation.After)
                    {

                        result = RemotingServices.ExecuteMessage(_targetDict[targetTypeName], method);
                        _aopAchieveDict[aopMethod.NameSpaceClass].AfterAchieve(result);
                    }
                    else
                    {
                        bool check = _aopAchieveDict[aopMethod.NameSpaceClass].BeforeAchieve(method);
                        if (check)
                        {
                            result = RemotingServices.ExecuteMessage(_targetDict[targetTypeName], method);
                            _aopAchieveDict[aopMethod.NameSpaceClass].AfterAchieve(result);
                        }
                    }
                }
                else//不需要AOP拦截,直接执行目标方法
                {
                    result = RemotingServices.ExecuteMessage(_targetDict[targetTypeName], method);

                }

            }

            return result;
        }
    }
}


下面是需要被代理的类的特性,在生成特性时会自动创建其代理对象

using System;
using System.Runtime.Remoting.Proxies;
using System.Collections.Generic;

namespace AOPProxy.AOP
{
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public class AOPProxyBaseAttribute : ProxyAttribute
    {
        
        private static Dictionary<string, IAOPInterceptAchieveBase> _aopAchieveDict = new Dictionary<string, IAOPInterceptAchieveBase>();
        private static Dictionary<string, MarshalByRefObject> _targetDict = new Dictionary<string, MarshalByRefObject>();

        public AOPProxyBaseAttribute(Type type)
        {
            try
            {
                object obj = Activator.CreateInstance(type);

                if (obj is IAOPInterceptAchieveBase)
                {
                    if(_aopAchieveDict.ContainsKey(((IAOPInterceptAchieveBase)obj).GetType().FullName)==false)
                        _aopAchieveDict.Add(((IAOPInterceptAchieveBase)obj).GetType().FullName, (IAOPInterceptAchieveBase)obj);
                }
                else
                {
                    throw new ArgumentException("特性的参数必须是实现IAOPInterceptAchieve接口的对象");
                }
            }
            catch (MissingMemberException e)
            {
                throw new MissingMemberException("实现IAOPInterceptAchieve接口的自定义代理类必须定义无参的构造函数",e);
            }

        }

        //覆写CreateInstance函数,返回我们自建的代理
        //该方法会在需要被代理的类在实例化时被创建
        public override MarshalByRefObject CreateInstance(Type serverType)//serverType是被AOPAttribute修饰的类
        {
            //未初始化的实例的默认透明代理
            MarshalByRefObject target = base.CreateInstance(serverType); //得到未初始化的实例

            if (_targetDict.ContainsKey(serverType.FullName) == false)
                _targetDict.Add(serverType.FullName, target);

            //得到自定义的真实代理
            AOPProxyBase rp = AOPProxyBase.GetBaseProxyInstance(serverType, _targetDict, _aopAchieveDict);//new AOPProxyBase(serverType, _targetDict, _aopAchieveDict);
            return (MarshalByRefObject)rp.GetTransparentProxy();
        }
    }
}

下面是方法的特性,表示了被代理类的那些方法需要被拦截,以及需要拦截的位置

using System;

namespace AOPProxy.AOP
{
    [AttributeUsage(AttributeTargets.Method,AllowMultiple=false)]
    public class AOPMethodBaseAttribute : Attribute
    {
        private AOPLocation _aopLocation;
        private string _nameSpaceClass;

        public string NameSpaceClass
        {
            get { return _nameSpaceClass; }
            set { _nameSpaceClass = value; }
        }

        public AOPLocation AopLocation
        {
            get { return _aopLocation; }
            set { _aopLocation = value; }
        }

        public AOPMethodBaseAttribute(AOPLocation loc,string ncl)
        {
            this._aopLocation = loc;
            this._nameSpaceClass = ncl;
        }
    }

    public enum AOPLocation
    {
        Before,
        After,
        All
    }
}

最后就是一个拦截方法接口


using System.Runtime.Remoting.Messaging;

namespace AOPProxy.AOP
{
    /// <summary>
    /// 被拦截方法的前后的额外处理逻辑接口
    /// </summary>
    public interface IAOPInterceptAchieveBase
    {
        bool BeforeAchieve(IMethodCallMessage callMsg);
        bool AfterAchieve(IMethodReturnMessage returnMsg);
    }
}


测试代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AOPProxy.AOP;

namespace AOPProxy
{
    class Program
    {
        static void Main(string[] args)
        {


            Test1Instance t1 = new Test1Instance();
            t1.Rxb1Method();


            Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
            Test2Instance t = new Test2Instance();
            t.Rxb2Method();
            t.Test2Method("我是目标方法的参数");

            Console.ReadLine();

        }
    }

    [AOPProxyBaseAttribute(typeof(AOPDataProxy))]
    [AOPProxyBaseAttribute(typeof(AOPLogProxy))]
    public class Test2Instance : TestBase
    {

        [AOPMethodBaseAttribute(AOPLocation.All, "AOPProxy.AOPDataProxy")]
        public string Test2Method(string s)
        {
            Console.WriteLine("TestMethod2-Action…要被拦截的方法…");
            return "rxb";
        }

        [AOPMethodBaseAttribute(AOPLocation.All, "AOPProxy.AOPLogProxy")]
        public void Rxb2Method()
        {
            Console.WriteLine("RxbMethod2-Action…要被拦截的方法…");
        }

    }

    [AOPProxyBaseAttribute(typeof(AOPLogProxy))]
    public class Test1Instance : TestBase
    {

        public string Test1Method(string s)
        {
            Console.WriteLine("TestMethod1-Action…要被拦截的方法…");
            return "rxb";
        }

        [AOPMethodBaseAttribute(AOPLocation.Before, "AOPProxy.AOPLogProxy")]
        public void Rxb1Method()
        {
            Console.WriteLine("RxbMethod1-Action…要被拦截的方法…");
        }

    }

    public class TestBase : ContextBoundObject{}
}

运行结果如下:



你可能感兴趣的:(AOP,realproxy,ProxyAttribute)