Subject:
一个泛型的 multicast delegate 实现
[Print This Page]
Author:
zzzl
Time:
2011-1-12 17:09
Subject:
一个泛型的 multicast delegate 实现
这个精巧的方法不是我想出来的,但挺不错的,所以在这推荐给大家,来源于:
https://forums.embarcadero.com/thread.jspa?threadID=47819
源代码我下载好了,放在附件里了。
下面的内容是原文中的用法示例,我只是翻译了一下,这样即使你不了解 multicast delegate 也可以快速看到这个方法的效果。
*****************************************************************************************
在我的multicast delegate方法里,TDelegate<T>可以被声明成象下面这样:
TSomeForm
=
class
(
TForm
)
private
FOnChange
:
TDelegate
<
TNotifyEvent
>;
end
;
TDelegate<TNotifyEvent>类型不需要创建,销毁,或其它的什么管理。它是一个用于引用过程的简单泛型存储器。
要给FOnChange增加一个事件,你可以这样写:
FOnChange.Add(ChangeHandlerOne);
FOnChange.Add(ChangeHandlerTwo);
注意FOnChange不需要初始化,而多个事件过程就可以被加进来。在这个示例里用的一个句柄过程是这样的:
procedure
TSomeForm
.
ChangeHandlerOne
(
Sender
:
TObject
);
begin
ShowMessage
(
'Change event one fired'
);
end
;
如果要移除一个事件句柄你可以这样写:
FOnChange.Remove(ChangeHandlerOne);
如果要调用事件列表,你可以这样写:
procedure
TSomeForm
.
DoChange
(
Sender
:
TObject
);
var
Event
:
TNotifyEvent
;
begin
for
Event
in
FOnChange
do
Event
(
Sender
);
end
;
在调用事件之前,你不需要检测FOnChange或事件是否已分配。
你也可以通过特定的接口,约束访问add和remove方法的外部代码。
IDelegate
<
T
>
=
interface
procedure
Add
(
const
Handler
:
T
);
procedure
Remove
(
const
Handler
:
T
);
end
;
使用这个接口的话,你可以象这样通过属性暴露FOnChange
private
function
GetOnChange
:
IDelegate
<
TNotifyEvent
>;
public
property
OnChange
:
IDelegate
<
TNotifyEvent
>
read
GetOnChange
;
...
function
TSomeForm
.
GetOnChange
:
IDelegate
<
TNotifyEvent
>;
begin
Result
:=
FOnChange
;
end
;
这样的效果就是,外部代码可以在FonChange上增加和移除代码,但不能调用与FOnChange关联的事件过程
更进一步,你可以自定义delegate类型。
TNotifyHandler
=
reference
to
procedure
(
Sender
:
TObject
);
TNotifyDelegate
=
TDelegate
<
TNotifyHandler
>;
INotifyDelegate
=
IDelegate
<
TNotifyHandler
>;
总的来说,所有的东西都可以使用类似的代码放在一起。请注意,没有必要创建、摧毁或管理FOnChange事件。
type
TSomeForm
=
class
(
TForm
)
private
FOnChange
:
TNotifyDelegate
;
function
GetOnChange
:
INotifyDelegate
;
protected
procedure
DoChange
(
Sender
:
TObject
);
virtual
;
public
property
OnChange
:
INotifyDelegate
read
GetOnChange
;
end
;
...
procedure
TSomeForm
.
DoChange
(
Sender
:
TObject
);
var
Event
:
TNotifyHandler
;
begin
for
Event
in
FOnChange
do
Event
(
Sender
);
end
;
function
TSomeForm
.
GetOnChange
:
INotifyDelegate
;
begin
Result
:=
FOnChange
;
end
;
然后,其它的代码可以追加/添加事件名柄,像这样:
SomeForm.OnChange.Add(SomeFormChanged);
SomeForm.OnChange.Remove(SomeFormChanged);
Attachment:
Delegates.zip
(2011-1-12 17:09, 914 bytes) / Download count 108
http://bbs.cnpack.org/attachment.php?aid=806
Author:
khzide
Time:
2011-1-19 09:59
我怎么觉得IDelegate这个限制有点太多余阿. 只能add,remove,不能调用,这个限制没有实际意思. 就像private,public一样. 必要时候是有必要直接调用private成员的. 这个约定是口头的,让别人知道就可以了.没必要完全限制住.
Welcome to CnPack Forum (http://bbs.cnpack.org/)
Powered by Discuz! 5.0.0