8
8
namespace Microsoft . ClearScript
9
9
{
10
10
/// <summary>
11
- /// Represents a host event source.
11
+ /// Provides the base implementation for a host event source.
12
12
/// </summary>
13
- /// <typeparam name="T">The event handler delegate type.</typeparam>
14
- public class EventSource < T >
13
+ public abstract class EventSource
15
14
{
16
- private readonly ScriptEngine engine ;
17
-
18
15
internal EventSource ( ScriptEngine engine , object source , EventInfo eventInfo )
19
16
{
20
17
MiscHelpers . VerifyNonNullArgument ( engine , nameof ( engine ) ) ;
21
18
MiscHelpers . VerifyNonNullArgument ( eventInfo , nameof ( eventInfo ) ) ;
22
19
23
- if ( eventInfo . EventHandlerType != typeof ( T ) )
24
- {
25
- throw new ArgumentException ( "Invalid event type" , nameof ( eventInfo ) ) ;
26
- }
27
-
28
- this . engine = engine ;
20
+ Engine = engine ;
29
21
Source = source ;
30
22
EventInfo = eventInfo ;
31
23
}
32
24
25
+ internal ScriptEngine Engine { get ; }
26
+
27
+ internal abstract Type HandlerType { get ; }
28
+
33
29
internal object Source { get ; }
34
30
35
31
internal EventInfo EventInfo { get ; }
@@ -42,33 +38,68 @@ internal EventSource(ScriptEngine engine, object source, EventInfo eventInfo)
42
38
/// Connects the host event source to the specified script handler function.
43
39
/// </summary>
44
40
/// <param name="scriptFunc">The script function that will handle the event.</param>
45
- /// <returns>An <see cref="EventConnection{T} "/> that represents the connection.</returns>
46
- public EventConnection < T > connect ( object scriptFunc )
41
+ /// <returns>An <see cref="EventConnection"/> that represents the connection.</returns>
42
+ public EventConnection connect ( object scriptFunc )
47
43
{
48
44
MiscHelpers . VerifyNonNullArgument ( scriptFunc , nameof ( scriptFunc ) ) ;
49
- return engine . CreateEventConnection < T > ( Source , EventInfo , DelegateFactory . CreateDelegate ( engine , scriptFunc , typeof ( T ) ) ) ;
45
+ return Engine . CreateEventConnection ( HandlerType , Source , EventInfo , DelegateFactory . CreateDelegate ( Engine , scriptFunc , HandlerType ) ) ;
50
46
}
51
47
52
48
// ReSharper restore InconsistentNaming
53
49
54
50
#endregion
55
51
}
56
52
57
- internal interface IEventConnection
53
+ /// <summary>
54
+ /// Represents a host event source.
55
+ /// </summary>
56
+ /// <typeparam name="T">The event handler delegate type.</typeparam>
57
+ public sealed class EventSource < T > : EventSource
58
58
{
59
- void Break ( ) ;
59
+ internal EventSource ( ScriptEngine engine , object source , EventInfo eventInfo )
60
+ : base ( engine , source , eventInfo )
61
+ {
62
+ if ( eventInfo . EventHandlerType != typeof ( T ) )
63
+ {
64
+ throw new ArgumentException ( "Invalid event type (handler type mismatch)" , nameof ( eventInfo ) ) ;
65
+ }
66
+ }
67
+
68
+ #region EventSource overrides
69
+
70
+ internal override Type HandlerType => typeof ( T ) ;
71
+
72
+ #endregion
73
+
74
+ #region script-callable interface
75
+
76
+ // ReSharper disable InconsistentNaming
77
+
78
+ /// <summary>
79
+ /// Connects the host event source to the specified script handler function.
80
+ /// </summary>
81
+ /// <param name="scriptFunc">The script function that will handle the event.</param>
82
+ /// <returns>An <see cref="EventConnection{T}"/> that represents the connection.</returns>
83
+ public new EventConnection < T > connect ( object scriptFunc )
84
+ {
85
+ MiscHelpers . VerifyNonNullArgument ( scriptFunc , nameof ( scriptFunc ) ) ;
86
+ return Engine . CreateEventConnection < T > ( Source , EventInfo , DelegateFactory . CreateDelegate ( Engine , scriptFunc , typeof ( T ) ) ) ;
87
+ }
88
+
89
+ // ReSharper restore InconsistentNaming
90
+
91
+ #endregion
60
92
}
61
93
62
94
/// <summary>
63
- /// Represents a connection between a host event source and a script handler function.
95
+ /// Provides the base implementation for a connection between a host event source and a script handler function.
64
96
/// </summary>
65
- /// <typeparam name="T">The event handler delegate type.</typeparam>
66
- public class EventConnection < T > : IEventConnection
97
+ public abstract class EventConnection
67
98
{
68
99
private readonly ScriptEngine engine ;
69
100
private readonly object source ;
70
- private readonly EventInfo eventInfo ;
71
- private readonly Delegate handler ;
101
+ private readonly MethodInfo removeMethod ;
102
+ private readonly object [ ] parameters ;
72
103
private readonly InterlockedOneWayFlag brokenFlag = new InterlockedOneWayFlag ( ) ;
73
104
74
105
internal EventConnection ( ScriptEngine engine , object source , EventInfo eventInfo , Delegate handler )
@@ -77,17 +108,28 @@ internal EventConnection(ScriptEngine engine, object source, EventInfo eventInfo
77
108
MiscHelpers . VerifyNonNullArgument ( handler , nameof ( handler ) ) ;
78
109
MiscHelpers . VerifyNonNullArgument ( eventInfo , nameof ( eventInfo ) ) ;
79
110
80
- if ( eventInfo . EventHandlerType != typeof ( T ) )
111
+ if ( ! MiscHelpers . Try ( out var addMethod , ( ) => eventInfo . GetAddMethod ( true ) ) || ( addMethod == null ) )
81
112
{
82
- throw new ArgumentException ( "Invalid event type" , nameof ( eventInfo ) ) ;
113
+ throw new ArgumentException ( "Invalid event type (no accessible add method)" , nameof ( eventInfo ) ) ;
114
+ }
115
+
116
+ if ( ! MiscHelpers . Try ( out removeMethod , ( ) => eventInfo . GetRemoveMethod ( true ) ) || ( removeMethod == null ) )
117
+ {
118
+ throw new ArgumentException ( "Invalid event type (no accessible remove method)" , nameof ( eventInfo ) ) ;
83
119
}
84
120
85
121
this . engine = engine ;
86
122
this . source = source ;
87
- this . eventInfo = eventInfo ;
88
- this . handler = handler ;
89
123
90
- eventInfo . AddEventHandler ( source , handler ) ;
124
+ addMethod . Invoke ( source , parameters = new object [ ] { handler } ) ;
125
+ }
126
+
127
+ internal void Break ( )
128
+ {
129
+ if ( brokenFlag . Set ( ) )
130
+ {
131
+ removeMethod . Invoke ( source , parameters ) ;
132
+ }
91
133
}
92
134
93
135
#region script-callable interface
@@ -105,17 +147,21 @@ public void disconnect()
105
147
// ReSharper restore InconsistentNaming
106
148
107
149
#endregion
150
+ }
108
151
109
- #region IEventConnection implementation
110
-
111
- void IEventConnection . Break ( )
152
+ /// <summary>
153
+ /// Represents a connection between a host event source and a script handler function.
154
+ /// </summary>
155
+ /// <typeparam name="T">The event handler delegate type.</typeparam>
156
+ public sealed class EventConnection < T > : EventConnection
157
+ {
158
+ internal EventConnection ( ScriptEngine engine , object source , EventInfo eventInfo , Delegate handler )
159
+ : base ( engine , source , eventInfo , handler )
112
160
{
113
- if ( brokenFlag . Set ( ) )
161
+ if ( eventInfo . EventHandlerType != typeof ( T ) )
114
162
{
115
- eventInfo . RemoveEventHandler ( source , handler ) ;
163
+ throw new ArgumentException ( "Invalid event type ( handler type mismatch)" , nameof ( eventInfo ) ) ;
116
164
}
117
165
}
118
-
119
- #endregion
120
166
}
121
167
}
0 commit comments