@@ -15,6 +15,66 @@ namespace System.Reactive
15
15
/// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
16
16
public abstract class EventPatternSourceBase < TSender , TEventArgs >
17
17
{
18
+ private sealed class Observer : ObserverBase < EventPattern < TSender , TEventArgs > > , ISafeObserver < EventPattern < TSender , TEventArgs > >
19
+ {
20
+ private bool _isDone ;
21
+ private bool _isAdded ;
22
+ private readonly Delegate _handler ;
23
+ private readonly object _gate = new object ( ) ;
24
+ private readonly Action < TSender , TEventArgs > _invoke ;
25
+ private readonly EventPatternSourceBase < TSender , TEventArgs > _sourceBase ;
26
+
27
+ public Observer ( EventPatternSourceBase < TSender , TEventArgs > sourceBase , Delegate handler , Action < TSender , TEventArgs > invoke )
28
+ {
29
+ _handler = handler ;
30
+ _invoke = invoke ;
31
+ _sourceBase = sourceBase ;
32
+ }
33
+
34
+ protected override void OnNextCore ( EventPattern < TSender , TEventArgs > value )
35
+ {
36
+ _sourceBase . _invokeHandler ( _invoke , value ) ;
37
+ }
38
+
39
+ protected override void OnErrorCore ( Exception error )
40
+ {
41
+ Remove ( ) ;
42
+ error . Throw ( ) ;
43
+ }
44
+
45
+ protected override void OnCompletedCore ( )
46
+ {
47
+ Remove ( ) ;
48
+ }
49
+
50
+ private void Remove ( )
51
+ {
52
+ lock ( _gate )
53
+ {
54
+ if ( _isAdded )
55
+ {
56
+ _sourceBase . Remove ( _handler ) ;
57
+ }
58
+ else
59
+ {
60
+ _isDone = true ;
61
+ }
62
+ }
63
+ }
64
+
65
+ public void SetResource ( IDisposable resource )
66
+ {
67
+ lock ( _gate )
68
+ {
69
+ if ( ! _isDone )
70
+ {
71
+ _sourceBase . Add ( _handler , resource ) ;
72
+ _isAdded = true ;
73
+ }
74
+ }
75
+ }
76
+ }
77
+
18
78
private readonly IObservable < EventPattern < TSender , TEventArgs > > _source ;
19
79
private readonly Dictionary < Delegate , Stack < IDisposable > > _subscriptions ;
20
80
private readonly Action < Action < TSender , TEventArgs > , /*object,*/ EventPattern < TSender , TEventArgs > > _invokeHandler ;
@@ -50,50 +110,18 @@ protected void Add(Delegate handler, Action<TSender, TEventArgs> invoke)
50
110
throw new ArgumentNullException ( nameof ( invoke ) ) ;
51
111
}
52
112
53
- var gate = new object ( ) ;
54
- var isAdded = false ;
55
- var isDone = false ;
56
-
57
- var remove = new Action ( ( ) =>
58
- {
59
- lock ( gate )
60
- {
61
- if ( isAdded )
62
- {
63
- Remove ( handler ) ;
64
- }
65
- else
66
- {
67
- isDone = true ;
68
- }
69
- }
70
- } ) ;
71
-
113
+ var observer = new Observer ( this , handler , invoke ) ;
72
114
//
73
115
// [OK] Use of unsafe Subscribe: non-pretentious wrapper of an observable in an event; exceptions can occur during +=.
74
116
//
75
- var d = _source . Subscribe /*Unsafe*/ (
76
- x => _invokeHandler ( invoke , /*this,*/ x ) ,
77
- ex => { remove ( ) ; ex . Throw ( ) ; } ,
78
- remove
79
- ) ;
80
-
81
- lock ( gate )
82
- {
83
- if ( ! isDone )
84
- {
85
- Add ( handler , d ) ;
86
- isAdded = true ;
87
- }
88
- }
117
+ observer . SetResource ( _source . Subscribe ( observer ) ) ;
89
118
}
90
119
91
120
private void Add ( Delegate handler , IDisposable disposable )
92
121
{
93
122
lock ( _subscriptions )
94
123
{
95
- var l = new Stack < IDisposable > ( ) ;
96
- if ( ! _subscriptions . TryGetValue ( handler , out l ) )
124
+ if ( ! _subscriptions . TryGetValue ( handler , out var l ) )
97
125
{
98
126
_subscriptions [ handler ] = l = new Stack < IDisposable > ( ) ;
99
127
}
@@ -118,8 +146,7 @@ protected void Remove(Delegate handler)
118
146
119
147
lock ( _subscriptions )
120
148
{
121
- var l = new Stack < IDisposable > ( ) ;
122
- if ( _subscriptions . TryGetValue ( handler , out l ) )
149
+ if ( _subscriptions . TryGetValue ( handler , out var l ) )
123
150
{
124
151
d = l . Pop ( ) ;
125
152
0 commit comments