先写一个人物接口
public interface IUserProcessor
{
string Name { get; set; }
int Age { get; set; }
void ShowMe();
}
然后写一个Student
类实现该接口
/// <summary>
/// 这里需要同时继承MarshalByRefObject,否则无法动态生成
/// </summary>
public class Student : MarshalByRefObject, IUserProcessor
{
public string Name { get; set; }
public int Age { get; set; }
public void ShowMe()
{
Console.WriteLine(ToString());
}
public override string ToString()
{
return $"大家好,我是{Name},我几年{Age}岁了";
}
}
接着就是核心部分,通常也是固定的,我们需要一个真实代理类(RealProxyHelper<T>)
,并且是泛型的,这样任何一个类(必须继承MarshalByRefObject,所以要约束一下)
我都可以传入并代理。最后要继承RealProxy
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
public class RealProxyHelper<T> : RealProxy where T : MarshalByRefObject
{
public override IMessage Invoke(IMessage msg)
{
throw new NotImplementedException();
}
}
之后,我们需要完善他
public class RealProxyHelper<T> : RealProxy
{
/// <summary>
/// 保存对象字段
/// </summary>
private readonly T target;
/// <summary>
/// 构造函数,需要调用父类构造方法
/// </summary>
/// <param name="_target"></param>
public RealProxyHelper(T _target) : base(typeof(T))
{
target = _target;
}
/// <summary>
/// 在方法执行前,做的一些事
/// </summary>
/// <param name="msg"></param>
private void DoSomethingBefore(IMessage message)
{
Console.WriteLine("在方法执行前,做的一些事");
}
/// <summary>
/// 在方法执行后,做的一些事
/// </summary>
/// <param name="message"></param>
private void DoSomethinfAfter(IMessage message)
{
Console.WriteLine("在方法执行后,做的一些事");
}
/// <summary>
/// 这里是要调用的方法
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public override IMessage Invoke(IMessage msg)
{
//之前
DoSomethingBefore(msg);
//调用方法接口
IMethodCallMessage callMessage = msg as IMethodCallMessage;
//callMessage.MethodBase.Invoke 执行调用方法
//target 对象
//callMessage.Args 方法的参数数组
//returnValue 方法的返回值
object returnValue = callMessage.MethodBase.Invoke(target, callMessage.Args);
//之后
DoSomethinfAfter(msg);
//返回调用方法的结果
/* 参数:
ret:
从中生成当前 System.Runtime.Remoting.Messaging.ReturnMessage 实例的被调用方法所返回的对象。
outArgs:
作为 out 参数从被调用方法返回的对象。
outArgsCount:
从被调用方法返回的 out 参数的数目。
callCtx:
方法调用的 System.Runtime.Remoting.Messaging.LogicalCallContext。
mcm:
对被调用方法进行的原始方法调用。
*/
return new ReturnMessage(returnValue, Array.Empty<object>(), 0, null, callMessage);
}
}
最后一步我们需要一个透明代理
/// <summary>
/// 透明代理
/// </summary>
public static class TransparentProxy
{
public static T Create<T>(IUserProcessor user) where T : MarshalByRefObject
{
//创建T实例
T instance = user as T;
RealProxyHelper<T> realProxy = new RealProxyHelper<T>(instance);
//获取当前实例的透明代理GetTransparentProxy()返回object 需要一个强制转换
T transparentProxy = realProxy.GetTransparentProxy() as T;
//这里返回的就是被装饰好的T
return transparentProxy;
}
}
以上几乎都是固定的,我们需要修改的仅仅是public override IMessage Invoke(IMessage msg){}
方法
现在,我们来开一下效果
static void Main(string[] args)
{
IUserProcessor student = new Student
{
Age = 22,
Name = "zxh"
};
student.ShowMe();
Console.WriteLine("***************************");
IUserProcessor newStudent = TransparentProxy.Create<Student>(student);
newStudent.ShowMe();
Console.Read();
}
在不修改User类的前提下, 我们实现了动态修改ShowMe
方法