EasyCsharp

来源:互联网 发布:安智市场软件下载 编辑:程序博客网 时间:2024/05/16 15:28

RealProxy实现代理

RealProxy实现 MarshalByRefObject对象的代理

对于MarshalByRefObject对象,可以使用下面的代码代理,并且对于传递到方法中的ref或out参数都可以正常返回。RemotingServices.ExecuteMessage传递的参数要求被代理对象是MarshalByRefObject类型。
Code

using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Runtime.Remoting;using System.Runtime.Remoting.Activation;using System.Runtime.Remoting.Messaging;using System.Runtime.Remoting.Proxies;using System.Text;using System.Threading.Tasks;using SampleCommon;namespace DynamicProxy{    public class DynamicProxy2    {        public static void Run()        {            G.SetLogPreStr("[DynamicProxy2]");            var bird = new Bird();            var proxy = EasyProxy2.NewProxy(bird);            proxy.Say();            int a = 2;            int b;            int c = proxy.Say(ref a, out b);            G.Log("a: {0} b:{1} c:{2}", a, b, c);        }    }    public interface ISay    {        void Say();        int Say(ref int a, out int b);    }    public class Bird : MarshalByRefObject, ISay    {        public Bird()        {            G.Log("this is bird construct");        }        public void Say()        {            G.Log("this is bird say");        }        public int Say(ref int a, out int b)        {            a++;            b = 1;            return a;        }    }    public class EasyProxy2 : RealProxy    {        private MarshalByRefObject _target;        private EasyProxy2(MarshalByRefObject target)            : base(target.GetType())        {            _target = target;        }        public override IMessage Invoke(IMessage msg)        {            var methodCall = (IMethodCallMessage) msg;            G.Log("begin method {0}", methodCall.MethodName);            IMethodReturnMessage myIMethodReturnMessage =                RemotingServices.ExecuteMessage(_target, methodCall);            G.Log("after method {0}", methodCall.MethodName);            return myIMethodReturnMessage;        }        public static T NewProxy<T>(T target) where T : MarshalByRefObject        {            var easyProxy = new EasyProxy2(target);            return (T) easyProxy.GetTransparentProxy();        }    }}

Result
这里写图片描述

RealProxy实现接口代理

这种方法将实现任意对象但需要继承特定接口的对象代理。
Code

using System;using System.Collections.Generic;using System.Linq;using System.Runtime.Remoting;using System.Runtime.Remoting.Messaging;using System.Runtime.Remoting.Proxies;using System.Text;using System.Threading.Tasks;using SampleCommon;namespace DynamicProxy{    public class DynamicProxy3    {        public static void Run()        {            G.SetLogPreStr("[DynamicProxy3]");            var bird = new Bird3();            var proxy = EasyProxy3<ISay>.NewProxy(bird);            proxy.Say();            int a = 2;            int b;            int c = proxy.Say(ref a, out b);            G.Log("a: {0} b:{1} c:{2}", a, b, c);        }    }    public class Bird3 : ISay    {        public Bird3()        {            G.Log("this is bird construct");        }        public void Say()        {            G.Log("this is bird say");        }        public int Say(ref int a, out int b)        {            a++;            b = 1;            return a;        }    }    public class EasyProxy3<T> : RealProxy    {        private object _target;        private EasyProxy3(object target)            : base(typeof(T))        {            _target = target;        }        public override IMessage Invoke(IMessage msg)        {            var methodCall = (IMethodCallMessage) msg;            G.Log("begin method {0}", methodCall.MethodName);            object[] args = null;            if (null != methodCall.Args && methodCall.Args.Length > 0)            {                args = new object[methodCall.Args.Length];                Array.Copy(methodCall.Args, 0, args, 0, methodCall.Args.Length);            }            var result = methodCall.MethodBase.Invoke(_target, args);            G.Log("after method {0}", methodCall.MethodName);            return new ReturnMessage(result, args,                args == null ? 0 : args.Length, methodCall.LogicalCallContext, methodCall);        }        public static T NewProxy(T target)        {            var easyProxy = new EasyProxy3<T>(target);            return (T)easyProxy.GetTransparentProxy();        }    }}

Result
这里写图片描述

上面两种方式实现的代理方法均无法对构造函数进行拦截

ProxyAttribute特性拦截

话不多说,详细内容都写在了注释里,被代理类必须继承自ContextBoundObject,这里给出完整示例。
Code

using System;using System.Collections.Generic;using System.IO.Ports;using System.Linq;using System.Runtime.Remoting;using System.Runtime.Remoting.Activation;using System.Runtime.Remoting.Contexts;using System.Runtime.Remoting.Messaging;using System.Runtime.Remoting.Proxies;using System.Runtime.Remoting.Services;using System.Security.Permissions;using System.Text;using System.Threading.Tasks;using SampleCommon;namespace DynamicProxy{    class DynamicProxy4    {        public static void Run()        {            G.SetLogPreStr("[DynamicProxy4]");            G.Log("begin");            //这里使用的new RayspyObject()并没有真正构建相关对象,而是被代理对象拦截重新构建,因此不要传递参数给其构造函数,无效            var server = new RayspyObject();            server.Say("hello");            G.Log("end");        }    }    /*     * 1.只有需要代理的对象继承自ContextBoundObject时再可以正常拦截,否则无法拦截,即使继承MarshalByRefObject也不行     * 2.特性是针对于类而非对象,因此构造函数中初始化的内容将无法正常传递     */    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]    [RaySpyProxy]     public class RayspyObject : ContextBoundObject    {        public RayspyObject()        {            G.Log("RayspyObject constructor called");        }        public void Say(string str)        {            G.Log("RayspyObject method Say invoke with msg: " + str);        }    }    [AttributeUsage(AttributeTargets.Class)]    [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)]    public class RaySpyProxyAttribute : ProxyAttribute    {        public override MarshalByRefObject CreateInstance(Type serverType)        {            MarshalByRefObject obj = base.CreateInstance(serverType);            var proxy = new ObjProxy(serverType, obj);            return (MarshalByRefObject)proxy.GetTransparentProxy();        }    }    public class ObjProxy : RealProxy    {        private MarshalByRefObject _target = null;        public ObjProxy(Type type, MarshalByRefObject target)            : base(type)        {            this._target = target;        }        public override IMessage Invoke(IMessage msg)        {            var methodCall = (IMethodCallMessage)msg;            G.Log("begin call {0}", methodCall.MethodName);            var methodConstruct = methodCall as IConstructionCallMessage;            IMethodReturnMessage back = null;            //构造函数,只有ContextBoundObject(Inherit from MarshalByRefObject)对象才能截获构造函数            if (methodConstruct != null)            {                RealProxy defaultProxy = RemotingServices.GetRealProxy(_target);                //此时_target并没有真正构建                //下面这句是构建_target                defaultProxy.InitializeServerObject(methodConstruct);                //本类是一个RealProxy,它可通过GetTransparentProxy函数得到透明代理                back = EnterpriseServicesHelper.CreateConstructionReturnMessage(methodConstruct,                    (MarshalByRefObject) GetTransparentProxy());            }            /*             * MarshalByRefObject对象就可截获普通的调用消息,             * MarshalByRefObject对象告诉编译器,不能将其内部简单的成员函数优化成内联代码,             * 这样才能保证函数调用都能截获。             */            else            {                //可以进行参数验证?                back = RemotingServices.ExecuteMessage(_target, methodCall);            }            G.Log("end call {0}", methodCall.MethodName);            return back;        }    }}

Result
这里写图片描述

引用

[1] MSDN ProxyAttribute
[2] MSDN RealProxy
[3] .Net中的RealProxy实现AOP
[4] Proxy代理背后的原理