zoukankan      html  css  js  c++  java
  • .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;
            }
        }
    }
  • 相关阅读:
    linux redis安装 5.0.2
    Linux nginx安装步骤 centos7
    fastjson JSONObject.toJSONString 出现 $ref: "$."的解决办法(重复引用)
    docker redis安装及配置(外网访问 关闭安全限制 设置密码)
    JDK dump
    mysql8 修改root密码
    docker系列详解<二>之常用命令
    获取地理位置
    js调用摄像头
    点击时扩散效果
  • 原文地址:https://www.cnblogs.com/weiweithe/p/4522642.html
Copyright © 2011-2022 走看看