.Net动态代理Castle ( 了解创建动态代理 )

什么是动态代理?想很好的了解动态代理,就需先来了解代理的概念,代理
(Proxy)这个概念在现实生活中无处不在,比如房屋中介,它就是一个代理对象,
能代理行驶房东(可以理解为Target)的权力,除此之外中介可以对房东的权力添
加一些附加值,拦截房东的一些行为,如收取中介费。

  在设计模式中,有一种模式叫做代理模式,在GOF中这样写道:

  为其他对象提供一种代理以控制对这个对象的访问。

  接下来,为了方便大家了解,我还是以代码的形式来描述下中介与房东之间的
故事。

首先,先来抽象房东的接口


public interface ILandlordible
 {
     void RentHouse();
 }

 

  建立一个房东的类并实现接口


public class Landlord:ILandlordible
{
    public void RentHouse()
    {
        Console.WriteLine("房东收取租金!");
    }
}

  房东委托中介出租,现在建立一个中介的类:


public class Intermediary:ILandlordible
{
    private ILandlordible landlor;
 
    public Intermediary(ILandlordible landlor)
    {
        this.landlor = landlor;
    }
 
    private void CollectIntermediaryFees()
    {
        Console.WriteLine("中介收取服务费!");
    }
      
    public void RentHouse()
    {
        landlor.RentHouse();
        CollectIntermediaryFees();
    }
}

  可以看到关于Intermediary的实现

  1.首先实现一个ILandlordible的接口,因为它将具有房东出租房屋的权力

  2.然后类中保存着ILandlordible的引用,因为它将被委托房东的行为

  3.在RentHouse方法中,中介首先执行房东的行为,然后收取中介费。

  最后,中介跟房东之间的故事就要上演啦:


class RentHouseStoryGeneralProxyVersion
{
    static void Main(string[] args)
    {
        Console.WriteLine("房东委托中介帮其出租房屋!");
        ILandlordible landlord = new Intermediary(new
Landlord());
        Console.WriteLine("中介成功出租房屋");
        landlord.RentHouse();
    }
}

执行结果:    

  完成上面这个例子之后,想必大家对代理模式有了一定的了解,接下来将来讲
解动态代理模式。

  动态代理,我的理解是在运行时动态地产生代理类,进而产生代理对象。结合
中介这个例子,即中介类可以动态的产生,没有必要去自己实现它。

  要动态的产生一个或者拦截它的行为,在.NET平台下:

  1..NET Remoting中可以利用后门进行拦截,但是必须显示的继承
ContextBoundObject类,我觉得这个方案不是很好,因为往往具有分类学区分的类
之前的关系才会采用继承,而且会受到单继承的限制。

  2.Emit对IL直接进行操作,这个也是办法,但是我觉得过于复杂,而且没有必
要研究到那个深度,所以我也不是很推荐。

  3.在前面介绍的两种方法之间,我选取了一个折中的难度的方法,Castle.Net
<http://www.castleproject.org/> 是一个开源项目,它有一个动态代理的库能很
好地解决.NET平台下动态代理的问题,也被很多流行的框架所采用,如
NHibernate,Moq.

  我还是来个例子,将中介的例子改编成动态代理版本:

  首先根据代理,让我们来简单的了解下Castle中的ProxyGenerator这个类:


public class ProxyGenerator
{
    public ProxyGenerator();
    public ProxyGenerator(IProxyBuilder builder);
    public IProxyBuilder ProxyBuilder { get; }
    public T CreateClassProxy<T>(params IInterceptor[]
interceptors);
}

  这里我摘取了ProxyGenerator的一些片段,这个类可以从名字中很容易看出它
可以为我们动态地产生代理,但是仔细思考一下代理一定要有目标,如中介代理房
东,所以CreateClassProxy这个泛型的方法就是指定需要代理的目标,这样就可以
我某个特定的类产生代理。但是,仅仅指定目标是不够的,如中介它除了执行房东
的职责之外,中介这个代理对象还有自己额外的逻辑,如收取服务费用。所以
CreateClassProxy提供了一个可变的参数IInterceptor数组。来看看IInterceptor接口

   public interface IInterceptor
    {
        void Intercept(IInvocation invocation);
    }

  当我在调用CreateClassProxy并传入实现了IInterceptor的对象时,所有的方
法都将被IInterceptor的Intercept方法所拦截,并且Interceptor的参数
IInvocation携带了所调用方法的所有信息,这样我们就可以对所调用的方法进行
全面的拦截,为所欲为。

  那我们就开始动手完成我们动态代理版的中介与房东之间的故事吧:

  继续沿用之前的ILandlordible接口,但对于Landlord(房东)类,由于需要
对它产生一个代理类,原理是需要继承于Landlord类,对源类的方法进行重载,利
用多态性,利用接口调用到重载的方法,所以对源类进行修改:



    public class Landlord:ILandlordible
    {
        public virtual void RentHouse()
        {
            Console.WriteLine("房东收取租金!");
        }
    }



  修改就是将源类的方法改为虚方法,看到这里,如果用过NHibernate的朋友,
是否觉得有点似曾相似,这就是为什么NHibernate的所以实体属性需要加上
Virtual关键字,关于原因我将在下一篇文章中跟大家一起分享。

  至于Intermediary(中介)类将由动态代理产生,所以就将不再使用,现在问
题的核心就在于怎么利用Castle实现代理类,并添加收取服务费的逻辑。

  首先建立一个拦截器实现IInterceptor接口



    public class IntermediaryIntercetor:IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            //执行房东的逻辑
            invocation.Proceed();
            CollectIntermediaryFees();
        }

        private void CollectIntermediaryFees()
        {
            Console.WriteLine("中介收取服务费!");
        }
    }



  有了这个拦截器就可以开始动态代理版的故事啦:



    class RentHouseStroyDynamicProxyVersion
    {
        static void Main(string[] args)
        {
            Console.WriteLine("房东委托中介帮其出租房屋!");
            Landlord proxyLandlord = CreateLandlordProxy();
            Console.WriteLine("中介成功出租房屋");
            proxyLandlord.RentHouse();
        }

        private static Landlord CreateLandlordProxy()
        {
            ProxyGenerator proxyGenerator = new ProxyGenerator();
            Landlord proyLandlord = proxyGenerator.CreateClassProxy<Landlord>(new IntermediaryIntercetor());
            return proyLandlord;
        }
    }

结果:



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值