-
Notifications
You must be signed in to change notification settings - Fork 1
/
Nathan.EventDispatcher.pas
108 lines (90 loc) · 2.74 KB
/
Nathan.EventDispatcher.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
unit Nathan.EventDispatcher;
interface
uses
System.Classes,
System.SysUtils,
System.Generics.Collections,
System.Generics.Defaults;
{$M+}
type
{$REGION 'Demo'}
// http://tech.turbu-rpg.com/30/under-the-hood-of-an-anonymous-method
// https://stackoverflow.com/questions/39955052/how-are-anonymous-methods-implemented-under-the-hood
// http://www.deltics.co.nz/blog/posts/586
// https://stackoverflow.com/questions/17533381/assign-an-anonymous-method-to-an-interface-variable-or-parameter
// INathanEventDispatcher = interface
// ['{E2DFECB0-831E-4F56-85D7-46AC4D9A77EE}']
// function Attach(Closure: TProc): TInnerTestMethod;
// end;
//
// TNathanEventDispatcher = class(TInterfacedObject, INathanEventDispatcher)
// strict private
// class var FInstance: INathanEventDispatcher;
// strict protected
// FClosure: TProc;
// procedure OnEvent();
// public
// class function Construct(Closure: TProc): TInnerTestMethod;
//
// function Attach(Closure: TProc): TInnerTestMethod;
// end;
{$ENDREGION}
TInnerProcedureOfObject = procedure of object;
TInnerProcOfObj = type TInnerProcedureOfObject;
INathanEventDispatcher<T> = interface
['{629122A7-4D07-432D-B638-3F2A0D0AC88E}']
function Attach(Closure: TProc): TInnerProcOfObj;
end;
TNathanEventDispatcher<T> = class(TInterfacedObject, INathanEventDispatcher<T>)
strict private
class var FInstance: INathanEventDispatcher<T>;
strict protected
FClosure: TProc;
procedure OnEvent();
public
class function Construct(Closure: TProc): TInnerProcOfObj;
function Attach(Closure: TProc): TInnerProcOfObj;
end;
{$M-}
implementation
{$REGION 'Demo'}
//{ TNathanEventDispatcher }
//
//class function TNathanEventDispatcher.Construct(Closure: TProc): TInnerTestMethod;
//begin
// if (not Assigned(FInstance)) then
// FInstance := TNathanEventDispatcher.Create;
//
// Result := FInstance.Attach(Closure);
//end;
//
//function TNathanEventDispatcher.Attach(Closure: TProc): TInnerTestMethod;
//begin
// FClosure := Closure;
// Result := OnEvent;
//end;
//
//procedure TNathanEventDispatcher.OnEvent;
//begin
// if Assigned(FClosure) then
// FClosure()
//end;
{$ENDREGION}
{ TNathanEventDispatcherT<T> }
class function TNathanEventDispatcher<T>.Construct(Closure: TProc): TInnerProcOfObj;
begin
if (not Assigned(FInstance)) then
FInstance := TNathanEventDispatcher<T>.Create;
Result := FInstance.Attach(Closure);
end;
function TNathanEventDispatcher<T>.Attach(Closure: TProc): TInnerProcOfObj;
begin
FClosure := Closure;
Result := OnEvent; // Result := (IInterface(Pointer(@OnEvent)^)) as T;
end;
procedure TNathanEventDispatcher<T>.OnEvent;
begin
if Assigned(FClosure) then
FClosure;
end;
end.