鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 编程语言开发 > delphi > >

利用RTTI实现Delphi的多播事件代理研究

来源:互联网 作者:佚名 时间:2013-10-17 15:01
我们知道Delphi的每个对象可以包含多个Property,Property中可以是方法,例如TButton.OnClick属性。Delphi提供的仅仅是 一对一的设置,无法直接让TButton.OnClick去调用多个方法,而Java中采用Listener模式有类似AddListener方法提供多播。 Delphi多播的思想

  我们知道Delphi的每个对象可以包含多个Property,Property中可以是方法,例如TButton.OnClick属性。Delphi提供的仅仅是

一对一的设置,,无法直接让TButton.OnClick去调用多个方法,而Java中采用Listener模式有类似AddListener方法提供多播。

Delphi多播的思想源于Allen Bauer的Blog:,

cnWizard的武稀松大侠在此思想基础上实现了Win32的Delphi多播机制见:,并且应用于cnWizard;

开源项目DSharp实现了更加完整的多播机制,可提供基于接口的多播,见:https://code.google.com/p/delphisorcery/

本人希望借鉴前人的基础上,实现一个对象的事件多播代理,即TEventAgent是一个TObject的事件多播代理器,将一个TObject传给TEventAgent后, TEventAgent扫描TObject所有事件,并为每个事件提供多播功能。

下面程序是一个简单示例,引用了 DSharp.Core.Events.pas单元,并在Delphi XE3 测试成功.

 

1 unit utObjEventAgent; System.Generics.Collections, DSharp.Core.Events, System.TypInfo, Classes; TEventLinker=class(DSharp.Core.Events.TEvent) //单个事件的多播器 FLinkedObject: TObject; 11 FLinkedProperty: PPropInfo; 12 FOriginal:TMethod; 13 14 FEventTypeData:PTypeData; 15 FEventName:String; 16 procedure MethodAdded(const Method: TMethod); override; 17 procedure MethodRemoved(const Method: TMethod); override; 18 procedure Notify(Sender: TObject; const Item: TMethod; 19 Action: System.Generics.Collections.TCollectionNotification); override; 20 property Owner; 21 property RefCount; Create(LinkedObj:TObject; LinkedPrpt:PPropInfo); 24 destructor Destroy; override; 25 end; 26 27 TEventAgent=class //对象的事件多播代理 FOwner:TObject; 30 FPropList: PPropList; 31 FNameList:TDictionary<String, TEventLinker>; 32 procedure Prepare; virtual; 33 procedure Clear; Create(aOwner:TObject); virtual; 36 destructor Destroy;override; 37 function GetEventCount: Int32; 38 function GetEventName(Index: Int32): PWideChar; 39 procedure AddEventNotifier(EventName: String; const NotifierMethod: TMethod);overload; // 添加事件处理函数 40 procedure RemoveEventNotifier(EventName: String; const NotifierMethod: TMethod);overload; // 移除时间处理函数 41 end; System.Rtti; TEventLinker.Create(LinkedObj:TObject; LinkedPrpt:PPropInfo); Create(LinkedPrpt.PropType^, nil); 52 FLinkedObject:=LinkedObj; 53 FLinkedProperty:=LinkedPrpt; 54 FEventName:=FLinkedProperty^.Name; 55 FOriginal:=GetMethodProp(FLinkedObject, FLinkedProperty); 56 SetMethodProp(FLinkedObject, FLinkedProperty, Self.GetInvoke); 57 if Assigned(FOriginal.Data) and Assigned(FOriginal.Code) then Add(FOriginal); //将原事件方法加入多播列表 58 end; TEventLinker.Destroy; SetMethodProp(FLinkedObject, FLinkedProperty, FOriginal); 63 inherited; 64 end; TEventLinker.MethodAdded(const Method: TMethod); ; TEventLinker.MethodRemoved(const Method: TMethod); ; TEventLinker.Notify(Sender: TObject; const Item: TMethod; 75 Action: System.Generics.Collections.TCollectionNotification); ; TEventAgent.AddEventNotifier(EventName: String; 82 const NotifierMethod: TMethod); V:TEventLinker; FNameList.TryGetValue(EventName, V) V.IndexOf(NotifierMethod)< V.Add(NotifierMethod); 90 end; 91 end; TEventAgent.Clear; Item: TPair<String, TEventLinker>; Item in FNameList do 98 Item.Value.Free; 99 FNameList.Clear; 100 if Assigned(FPropList) then FreeMem(FPropList); 101 end; TEventAgent.Create(aOwner:TObject); Create; 106 FNameList:=TDictionary<String, TEventLinker>.Create; 107 FOwner:=aOwner; 108 Prepare; 109 end; TEventAgent.Destroy; Clear; 114 FNameList.Free; 115 inherited; 116 end; TEventAgent.GetEventCount: Int32; Result:=FNameList.Count; 121 end; TEventAgent.GetEventName(Index: Int32): PWideChar; Result:=PWideChar(FNameList.Keys.ToArray[Index]); 126 end; TEventAgent.Prepare; N, i:Integer; 131 Linker:TEventLinker; 132 Context: TRttiContext; Clear; 135 N:=GetPropList(FOwner.ClassInfo, FPropList); N-FPropList^[i].PropType^.Kind = tkMethod FPropList[i].GetProc=nil then Continue; 140 Linker:=TEventLinker.Create(FOwner, FPropList[i]); 141 Linker.FEventName:=FPropList[i].Name; 142 FNameList.Add(Linker.FEventName, Linker); 143 end; 144 end; TEventAgent.RemoveEventNotifier(EventName: String; 148 const NotifierMethod: TMethod); V:TEventLinker; FNameList.TryGetValue(EventName, V) V.Remove(NotifierMethod); 155 end; 156 end; .

网友评论
<