知识大全 Delphi中关于动态代理应用技巧

Posted

篇首语:千金一刻莫空度,老大无成空自伤。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Delphi中关于动态代理应用技巧相关的知识,希望对你有一定的参考价值。

Delphi中关于动态代理应用技巧  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

本来想上周末没能用DELPHI实现动态代理就算了 可是这几天却始终放不下这个想法 这实在是一个太美妙的想法了 而且在认真看了VCL对SOAP的实现后 现在至少有九成的把握可以实现这样一个动态代理     那么动态代理有什么用?  这要先从GoF的Proxy模式说起     假设有下面这样一个接口及其实现    >  现在 如果你是这个接口的用户 而这个接口及其实现者提供了一个     Foo : IFoo;    给你 其中Foo指向TFooImpl的一个实例 现在你有了IFoo的定义 和这个Foo实例 注意 你没有TFooImpl的定义和实现代码 如果现在要求你为所有的IFoo doSth增加事务功能(假设doSth被实现为对数据库作更新操作) 要怎么办?    GoF的Proxy模式就是解决方案之一    >>>  如果所示 首先要实现一个新的IFoo接口实现 TStaticProxy 其中用了一个属性FImpl记录了TFooImpl的实例 然后在 TStaticProxy中实现doSth和bar 并且将不需要变更的bar函数直接委托给FImpl处理 而在doSth的实现里加入事务处理即可 TStaticProxy的代码大致如下     TStaticProxy = class( TInterfacedObject IIFoo )  private  FImpl : IFoo;  public  constructor Create( aImpl : IFoo );  function doSth( ) : xxx;  function bar( ) : xxx;  end;    constructor TStaticProxy Create( aImpl : IFoo );  Begin  FImpl := aImpl;  End;    function TStaticProxy doSth( ) : xxx;  Begin  BeginTransaction;  Result := FImpl doSth( );  EndTransaction;  End;    function TStaticProxy bar( ) : xxx;  Begin  Result := FImpl bar( );  End;    然后 在所有需要用到Foo对象的地方 改用新的NewFoo对象 如下     var  NewFoo : IFoo;  Begin  NewFoo := TStaticProxy Create( Foo ) As IFoo;    // 之后就可以把NewFoo完全当作Foo一样使用了   End;    可见 我们通过了一个Proxy类代理了所有对IFoo接口的操作 相当于在从IFoo到TFooImpl之间插入了自己的代码 在某种程度上 这就是AOP所谓的 横切 当然如果你能有TFooImpl的代码的话 就简单了 只要如下    >>>  从TFooImpl派生一个TNewFooImpl 然后在其中Override一下TFooImpl中的doSth即可 然后就创建TNewFooImpl的实例来代替Foo引用即可     但问题就在于你必须拥用TFooImpl的代码 并且可以变更所提供的Foo实例 但这在很多时候是做不到的 除非不是用DELPHI 而是如 Python一类的动态语言^O^ 比如组件容器 比如远程实例等 还有像 虚代理 (就是当创建FImpl代价很高时 就在创建时只创建代理类 然后在真正需要时才创建FImpl的实例)    但上面这种静态代理还是很麻烦 首先 如果IFoo的成员函数很多的话 必须要一一为它们加上代理实现 其次 如果在应用中有很多接口需要代理时 就必须一一为它们写这样的专用代理类 第三 需要变更代理功能时 需要修改所有的代理类……    特别是像组件容器或是通用远程代理这样 对要实现的接口并不能确定的情况下 静态代理一点用也没有     所以我们需要 动态代理 我是在看了GIGIX发表在今年第一期《程序员》上的《动态代理的前世今生》一文后 虽然他说是的JAVA在 JDK 中提出的 在java lang reflect中的proxy 但这却让我突发奇想 发现其实完全可以在DELPHI里也实现这样一个动态代理     一个典型的动态代理如下    >>  这样 我们只需要把要增加在功能做成一个IInvocationHandler接口的实例 如图中的TFooInvHandler 然后动态创建一个支持IFoo接口的TDynamicProxy的实例 它是一个动态代理 只需要传入相应的参数 要实现的接口和相应的InvHandler实例即可 不需要为每个接口写一个代理 当然如GIGIX文中所说 对于C++来说 这个可以用模板实现 但问题在于模板归根到底是一种编译时的动态化技术 对于组件容器这样需要运行时动态化的应用 它还是不能实现 最后 InvHandler通过RTTI去调用具体的实现Foo     它的用法大致如下     TFooInvHandler = class( TInterfacedObject IInvocationHandler )  private  FImpl : IFoo;  public  constructor Create( aImpl : IFoo );  function Invoke( IID MethodName Args[] ) : xxx;  end;    constructor TFooInvHandler Create( aImpl : IFoo );  Begin  FImpl := aImpl;  End;    function TFooInvHandler Invoke( IID MethodName Args[] ) : xxx  Begin  If ( IID = IFoo ) AND ( MethodName = doSth ) Then  Begin  BeginTransaction;  Result := DoInvoke( FImpl IID MethodName Args[] );  EndTransaction;  End  Else  Result := DoInvoke( FImpl IID MethodName Args[] );  End;    var  Handler : IInvocationHandler;  NewFoo : IFoo;  Begin  Handler := TFooInvHandler Create( Foo );  NewFoo := TDynamicProxy Create( TypeInfo(IFoo) Handler ) As IFoo;    // 之后就可以把NewFoo完全当作Foo一样使用了   End;    注意 其中IInvocationHandler接口我还没想好要怎么定义 所以这段代码只是大致说明一下问题 另外 其中的DoInvoke就是通过RTTI来调用FImpl的     从上面的代码可以看到 TDynamicProxy通过参数IFoo动态生成了一个对IFoo接口的代理 并且通过Handler参数插入一个处理接口IInvocationHandler 由TDynamicProxy把对IFoo接口的调用全部转成对IInvocationHandler接口的调用 最后由TFooInvHandler类来视情况处理 在这里 可以通过运行时配置方式来动态决定是否需要切入事务所处理 需要对哪个接口的哪个方法切入     有了这样一个动态代理 还可以很方便地在InvocationHandler里切入如安全性检查 LOG等 这样的话 用DELPHI来实现AOP也不成问题了     现在我面临的问题就是 如何来定义这个IInvocationHandler     其实这里最主要的问题就是参数的传递的问题 接口可以用IID表示 方法可以用方法名 但参数变化太多了 一是数量不确定 可以有任意多个参数 二是类型不确定 三是传值参数和引用参数的问题 如前面那个例子用的是简单的办法 就是用一个不定长的Variant数组来记录 可以解决前两个问题 但第三个问题就比较麻烦 难道要用一个Tuple来作返回值?太麻烦了吧     在VCL的SOAP实现里是通过一个TInvContext在记录的 但这样的话对于Handler的开发者来说 就不得不面对TInvContext的内部复杂性 易用性太差 cha138/Article/program/Delphi/201311/8416

相关参考

知识大全 动态代理

  动态代理  要求测算一个类里面的某个方法的执行时间  直接在一个测试的方法中调用这个类的方法就可以了也可以直接的写在这个类的main方法里面  继承这个类对需要测算时间的方法进行重写方法中这样来写

知识大全 Java 实践: 用动态代理进行修饰

Java实践:用动态代理进行修饰  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  动态代理工具是j

知识大全 JAVA 动态代理

JAVA动态代理  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在目前的Java开发包中包含了对

知识大全 java动态代理Dynamic Proxy

java动态代理DynamicProxy  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  被代理对

知识大全 Java动态代理机制综合分析及扩展

Java动态代理机制综合分析及扩展  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Java动态代

知识大全 Delphi数据库的动态建立

Delphi数据库的动态建立  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  delphi最吸引人

知识大全 JVM技术,反射与动态代理

JVM技术,反射与动态代理  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Java程序的工作机制

知识大全 Java设计模式-----Proxy模式(动态代理)

Java设计模式-----Proxy模式(动态代理)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

知识大全 浅谈Java中用动态代理类实现记忆功能

浅谈Java中用动态代理类实现记忆功能  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  记忆是衍生

知识大全 Delphi 中自做动态显示的控件

Delphi中自做动态显示的控件  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Delp