《C#设计模式》--03.代理设计模式(结构型设计模式)
·
提示:以下是本篇文章正文内容,下面案例可供参考
一、基本概念
1)代理设计模式:为其他对象提供一种代理,以控制对这个对象的访问。
2)代理分类:
- 远程代理:为一个对象在不同的地址空间,提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实。客户端调用Web服务,会生成WebReference文件和文件夹,WebReference就是代理,使得客户端可以实现远程访问等功能。
- 虚拟代理,如果要创建开销很大的对象,可以通过代理来存放实例化需要很长时间的真实对象。打开一个很大的网页,除了文字先出现外,图片和视频等都是慢慢出现的。查询某个部门下所有的员工的信息,姓名、性别、年龄、毕业院校、部门、照片、slogen…
- 安全代理,用来控制真实对象的访问权限。例如订单系统,要求是:一旦订单被创建,只有订单的创建人才可以修改订单中的数据,其他人则不能修改
二、代码示例
普通代理
一个非常简单的例子
public class Swim
{
public virtual void Go()
{
Console.WriteLine("开始游泳!!!");
}
}
public class SwimProxy:Swim
{
public override void Go()
{
//目标方法执行前
Console.WriteLine("先进性热身运动!!!");
base.Go();
//目标方法执行后
Console.WriteLine("开始洗澡!!!");
}
}
使用案例
SwimProxy swimProxy = new SwimProxy();
swimProxy.Go();
通过代理模式,在目标方法执行前,执行后进行处理,甚至可以要求传入参数,来判断年纪过大不允许游泳,如果要这么做,做一些权限管控,可以使用非继承的方式,内部声明Swim对象即可。
动态代理
在编译期间不生成代理,而是在执行期间,动态创建代理类。
DispatchProxy基本使用
DispatchProxy是一个基于接口的动态代理工具类。
1)使用要求:如果当前类允许动态代理,则必须实现一个业务接口
2)注意:
- 动态代理生成的动态类对象是业务接口类型对象,所以只有实现了接口方法的具体方法才会被监听到执行
- 当前类的其他virtual方法如果不是来自业务接口,由于生成的代理对象是业务接口类型,无法调用
3)代码演示
/// <summary>
/// 一个接口
/// </summary>
public interface Sport
{
public void Swim();
public void Run();
}
/// <summary>
/// 实现类
/// </summary>
public class SportImpl: Sport
{
public void Swim()
{
Console.WriteLine("开始游泳!!!");
}
public void Run()
{
Console.WriteLine("跑步");
}
public void Run1()
{
Console.WriteLine("跑步");
}
}
/// <summary>
/// 实现类的动态代理类
/// </summary>
public class SportProxy : DispatchProxy
{
private SportImpl im=new SportImpl();
protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
{
//目标方法执行前
Console.WriteLine("目标方法执行前" + targetMethod.Name);
//目标方法执行
targetMethod.Invoke(im, args);
//目标方法执行后
Console.WriteLine("目标方法执行后" + targetMethod.Name);
return 0;
}
}
使用代码
Sport sport = SportProxy.Create<Sport,SportProxy>();
sport.Swim();
sport.Run();
DispatchProxy总结
1)如果我们每个类都需要代理,那么我们就要给每个类写一个代理类,显然是非常麻烦的
2)使用DispatchProxy需要的条件如下:
- 一个接口
- 一个实现了此接口的实现类
- 一个操作对象,用于代理类在真正执行时,需要调用的对象
3)代码示例
/// <summary>
/// 一个接口
/// </summary>
public interface Sport
{
public void Swim();
public void Run();
}
/// <summary>
/// 实现类
/// </summary>
public class SportImpl: Sport
{
public void Swim()
{
Console.WriteLine("开始游泳");
}
public void Run()
{
Console.WriteLine("开始跑步");
}
public virtual void Run1()
{
Console.WriteLine("跑步1");
}
}
/// <summary>
/// 通用动态代理类
/// </summary>
/// <typeparam name="TI">接口类型</typeparam>
/// <typeparam name="TImpl">实现接口的具体类类型</typeparam>
public class DynamicProxy<TI,TImpl>
{
/// <summary>
/// 操作对象
/// </summary>
public TI invokeObj { get; private set; }
public DynamicProxy(TImpl implObj)
{
if (implObj != null)
{
InnerProxy.implObj = implObj;
this.invokeObj = InnerProxy.Create<TI, InnerProxy>();
}
}
/// <summary>
/// 设置方法执行前执行的代码
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public DynamicProxy<TI, TImpl> SetBefore(Action<MethodInfo, object?[]?> action)
{
InnerProxy.before = action;
return this;
}
public DynamicProxy<TI, TImpl> SetAfter(Action<MethodInfo, object?[]?> after)
{
InnerProxy.after = after;
return this;
}
/// <summary>
/// 设置方法执行后执行的代码
/// </summary>
public class InnerProxy : DispatchProxy
{
public static TImpl implObj { get; set; }
public static Action<MethodInfo, object?[]?> before { get; set; }
public static Action<MethodInfo, object?[]?> after { get; set; }
protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
{
before(targetMethod,args);
var result=targetMethod.Invoke(implObj, args);
after(targetMethod, args);
return result;
}
}
}
使用案例
DynamicProxy<Sport, SportImpl> dynamicProxy = new DynamicProxy<Sport, SportImpl>(new SportImpl());
dynamicProxy.SetBefore((method, args) =>
{
Console.WriteLine("方法执行前...");
}).SetAfter((method, args) =>
{
Console.WriteLine("方法执行后...");
}).invokeObj.Swim();
更多推荐
所有评论(0)