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代理背后的原理