.net Aop 实现原理

本文实现所有继承BaseModel的类都通过代理拦截

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

namespace Soffice.DevelopFramework.Common.DataAccess
{
    [AopAttribute]
    public class BaseModel : ContextBoundObject
    {
        private Dictionary<string, object> Fields = new Dictionary<string, object>();

        public void AddField(string fieldName, object value)
        {
            Fields.Add(fieldName, value);
        }

        public Dictionary<string, object> GetFields()
        {
            return Fields;
        }
    }

    class AopAttribute : ProxyAttribute
    {
        public override MarshalByRefObject CreateInstance(Type serverType)
        {
            AopProxy realProxy = new AopProxy(serverType);
            return realProxy.GetTransparentProxy() as MarshalByRefObject;
        }
    }

    class AopProxy : RealProxy
    {
        MethodInfo method = null;
        public AopProxy(Type serverType)
            : base(serverType)
        {
            method = serverType.GetMethod("AddField");
        }
        public override IMessage Invoke(IMessage msg)
        {
            //消息拦截之后,就会执行这里的方法。
            if (msg is IConstructionCallMessage) // 如果是构造函数,按原来的方式返回即可。
            {
                IConstructionCallMessage constructCallMsg = msg as IConstructionCallMessage;
                IConstructionReturnMessage constructionReturnMessage = this.InitializeServerObject((IConstructionCallMessage)msg);
                RealProxy.SetStubData(this, constructionReturnMessage.ReturnValue);
                return constructionReturnMessage;
            }
            else if (msg is IMethodCallMessage) //如果是方法调用(属性也是方法调用的一种)
            {
                IMethodCallMessage callMsg = msg as IMethodCallMessage;
                object[] args = callMsg.Args;
                IMessage message;
                try
                {
                    if (callMsg.MethodName.StartsWith("set_") && args.Length == 1)
                    {
                        //这里检测到是set方法,然后应怎么调用对象的其它方法呢?
                        method.Invoke(GetUnwrappedServer(), new object[] { callMsg.MethodName.Substring(4), args[0] });//对属性进行调用
                    }
                    object o = callMsg.MethodBase.Invoke(GetUnwrappedServer(), args);
                    message = new ReturnMessage(o, args, args.Length, callMsg.LogicalCallContext, callMsg);
                }
                catch (Exception e)
                {
                    message = new ReturnMessage(e, callMsg);
                }
                return message;
            }
            return msg;
        }
    }
}

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。