1. 程式人生 > 實用技巧 >C#簡單實現Aop實體屬性攔截

C#簡單實現Aop實體屬性攔截

1

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

namespace AopTest.Entity
{
    class AopAttribute : ProxyAttribute
    {

        
public override MarshalByRefObject CreateInstance(Type serverType) { AopProxy realProxy = new AopProxy(serverType, base.CreateInstance(serverType)); return realProxy.GetTransparentProxy() as MarshalByRefObject; } } class AopProxy : RealProxy { MethodInfo Setmethod; MethodInfo ListenerLog; MarshalByRefObject _target
= null; public AopProxy(Type serverType, MarshalByRefObject target) : base(serverType) { _target = target; Setmethod = serverType.GetMethod("Set", BindingFlags.NonPublic | BindingFlags.Instance); ListenerLog = serverType.GetMethod("ListenerLog
", BindingFlags.NonPublic | BindingFlags.Instance); } public override IMessage Invoke(IMessage msg) { if (msg != null) { if (msg is IConstructionCallMessage) { IConstructionCallMessage constructCallMsg = msg as IConstructionCallMessage; //IConstructionReturnMessage constructionReturnMessage = this.InitializeServerObject((IConstructionCallMessage)msg); //RealProxy.SetStubData(this, constructionReturnMessage.ReturnValue); //return constructionReturnMessage; RealProxy defaultProxy = RemotingServices.GetRealProxy(_target); //如果不做下面這一步,_target還是一個沒有直正例項化被代理物件的透明代理, //這樣的話,會導致沒有直正構建物件。 defaultProxy.InitializeServerObject(constructCallMsg); //本類是一個RealProxy,它可通過GetTransparentProxy函式得到透明代理 return EnterpriseServicesHelper.CreateConstructionReturnMessage(constructCallMsg, (MarshalByRefObject)GetTransparentProxy()); } else if (msg is IMethodCallMessage) { IMethodCallMessage callMsg = msg as IMethodCallMessage; object[] args = callMsg.Args; //System.Windows.Forms.MessageBox.Show(callMsg.MethodBase.ToString()); IMethodReturnMessage methodReturnMessage; methodReturnMessage = RemotingServices.ExecuteMessage(_target, callMsg); if (callMsg.MethodName.StartsWith("set_") && args.Length == 1) { ListenerLog.Invoke(_target, new object[] { "Set", _target.GetType().Name, callMsg.MethodName.Substring(4), args[0] });//屬性進行呼叫 } else if (callMsg.MethodName.StartsWith("get_") && args.Length == 0) { //object val = callMsg.MethodBase.Invoke(_target, null); ListenerLog.Invoke(_target, new object[] { "Get", _target.GetType().Name, callMsg.MethodName.Substring(4), methodReturnMessage.ReturnValue });//屬性進行呼叫 } else if (callMsg.MethodName.Equals("FieldSetter") && args.Length == 3) { ListenerLog.Invoke(_target, new object[] { callMsg.MethodName, _target.GetType().Name, args[1], args[2] });//欄位進行呼叫 } else if (callMsg.MethodName.Equals("FieldGetter") && args.Length == 3) { callMsg.MethodBase.Invoke(_target, args); ListenerLog.Invoke(_target, new object[] { callMsg.MethodName, _target.GetType().Name, args[1], args[2] });//欄位進行呼叫 } else { ListenerLog.Invoke(_target, new object[] { callMsg.MethodName, _target.GetType().Name, args, methodReturnMessage.ReturnValue });//方法進行呼叫 } //methodReturnMessage = RemotingServices.ExecuteMessage(_target, callMsg); return methodReturnMessage; //IMessage message = null; //try //{ // MarshalByRefObject obj = GetUnwrappedServer(); // if (callMsg.MethodName.StartsWith("set_") && args.Length == 1) // { // method.Invoke(obj, new object[] { callMsg.MethodName.Substring(4), args[0] });//對屬性進行呼叫 // } // object o = callMsg.MethodBase.Invoke(obj, args); // message = new ReturnMessage(o, args, args.Length, callMsg.LogicalCallContext, callMsg); //} //catch (Exception e) //{ // message = new ReturnMessage(e, callMsg); //} //return message; } } return msg; } } }
View Code

Base類

using System;
using System.Diagnostics;
using System.Reflection;

namespace AopTest.Entity
{
    [AopAttribute]
    public abstract partial class AopBase : ContextBoundObject
    {
        protected void Set(object key, object value)
        {
            string loc = GetCallingLocation(9);
        }
        protected void ListenerLog(string MethodName, string entitytype, object key, object value)
        {
            string str = "";
            switch (MethodName)
            {
                case "Set":
                    str = GetCallingLocation(9) + entitytype + " 設定屬性 " + key + " 值為 " + value;
                    break;
                case "Get":
                    str = GetCallingLocation(9) + entitytype + " 讀取屬性 " + key + " 值為 " + value;
                    break;
                case "FieldSetter":
                    str = GetCallingLocation(9) + entitytype + " 設定欄位 " + key + " 值為 " + value;
                    break;
                case "FieldGetter":
                    str = GetCallingLocation(9) + entitytype + " 讀取欄位 " + key + " 值為 " + value;
                    break;
                default:
                    string parameter = "";
                    foreach (object obj in key as object[])
                    { parameter += obj.ToString() + ","; }
                    parameter = parameter.TrimEnd(',');
                    str = GetCallingLocation(9) + entitytype + "呼叫方法 " + MethodName + " 引數 " + parameter + " 返回 " + value.ToString();
                    break;
            }
            Logs(str);
        }
        private void Logs(string msg)
        {

        }
        private string GetCallingLocation(int index)
        {
            StackTrace trace = new StackTrace();
            MethodBase methodName = trace.GetFrame(index).GetMethod();
            string className = methodName.ReflectedType.Name;
            return className + ">>" + methodName.Name + ">>";
        }
    }
}
View Code

Test

namespace AopTest.Entity
{
    class test : AopBase
    {
        public int val = 0;
        public int Aa { get; set; }
        public string age { get; set; }

        public int add(int a, int b)
        {
            return a + b;
        }
        public static int add2(int a, int b)
        {
            return a + b;
        }
    }
}
View Code

            test tt = new test();
            tt.val = 5;
            int vv = tt.val;
            tt.age = "dfefe";
            string age = tt.age;

            int bb = tt.add(44, 55);

攔截效果

Form1>>button1_Click>>test 設定欄位 val 值為 5
Form1>>button1_Click>>test 讀取欄位 val 值為 5
Form1>>button1_Click>>test 設定屬性 age 值為 dfefe
Form1>>button1_Click>>test 讀取屬性 age 值為 dfefe
Form1>>button1_Click>>test呼叫方法 add 引數 44,55 返回 99