回答編集履歴

4

追記

2018/10/14 09:47

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -139,3 +139,207 @@
139
139
  そして Mouse イベントが起こるたびに Conversion から返された action を呼び出します。
140
140
 
141
141
  h は FromEvent の登録したデリゲートで、これを呼び出すことにより、以降のオブザーバーに e を渡します。
142
+
143
+
144
+
145
+ #追記
146
+
147
+
148
+
149
+ Observable.FromEvent の中ではだいたいこんなことが行われていると思います。
150
+
151
+
152
+
153
+ ```C#
154
+
155
+ using System;
156
+
157
+ using System.Collections.Generic;
158
+
159
+ using System.Diagnostics;
160
+
161
+ using System.Reactive.Linq;
162
+
163
+ using System.Windows.Forms;
164
+
165
+
166
+
167
+ namespace WindowsFormsApp1
168
+
169
+ {
170
+
171
+ public partial class Form1 : Form
172
+
173
+ {
174
+
175
+ public Form1()
176
+
177
+ {
178
+
179
+ InitializeComponent();
180
+
181
+ }
182
+
183
+
184
+
185
+ private void button1_Click(object sender, EventArgs args)
186
+
187
+ {
188
+
189
+ MyObservable<MouseEventHandler, MouseEventArgs>
190
+
191
+ .FromEvent(
192
+
193
+ h => (s, e) => h(e),
194
+
195
+ h => MouseMove += h,
196
+
197
+ h => MouseMove -= h)
198
+
199
+ .Subscribe(e =>
200
+
201
+ {
202
+
203
+ Debug.WriteLine($"({e.X},{e.Y})");
204
+
205
+ });
206
+
207
+ }
208
+
209
+ }
210
+
211
+
212
+
213
+ class MyObservable<TEventHandler, TEventArgs> : IObservable<TEventArgs>
214
+
215
+ where TEventArgs : EventArgs
216
+
217
+ where TEventHandler : MulticastDelegate
218
+
219
+ {
220
+
221
+ protected IList<IObserver<TEventArgs>> Observers { get; } = new List<IObserver<TEventArgs>>();
222
+
223
+ protected Action<TEventHandler> AddHandler { get; private set; }
224
+
225
+ protected Action<TEventHandler> RemoveHandler { get; private set; }
226
+
227
+ protected TEventHandler EventHandler { get; private set; }
228
+
229
+
230
+
231
+ public static IObservable<TEventArgs> FromEvent(
232
+
233
+ Func<Action<TEventArgs>, TEventHandler> conversion,
234
+
235
+ Action<TEventHandler> addHandler,
236
+
237
+ Action<TEventHandler> removeHandler)
238
+
239
+ {
240
+
241
+ var result = new MyObservable<TEventHandler, TEventArgs>();
242
+
243
+ result.AddHandler = addHandler;
244
+
245
+ result.RemoveHandler = removeHandler;
246
+
247
+ result.EventHandler = conversion(result.Handler);
248
+
249
+ result.AddHandler?.Invoke(result.EventHandler);
250
+
251
+ return result;
252
+
253
+ }
254
+
255
+
256
+
257
+ private void Handler(TEventArgs e)
258
+
259
+ {
260
+
261
+ foreach (var observer in Observers)
262
+
263
+ {
264
+
265
+ observer.OnNext(e);
266
+
267
+ }
268
+
269
+ }
270
+
271
+
272
+
273
+ public IDisposable Subscribe(IObserver<TEventArgs> observer)
274
+
275
+ {
276
+
277
+ Observers.Add(observer);
278
+
279
+ return new Disposable(this, observer);
280
+
281
+ }
282
+
283
+
284
+
285
+ protected void RemoveObserver(IObserver<TEventArgs> observer)
286
+
287
+ {
288
+
289
+ if (Observers.Count == 0) return;
290
+
291
+ Observers.Remove(observer);
292
+
293
+ if (Observers.Count == 0)
294
+
295
+ {
296
+
297
+ RemoveHandler?.Invoke(EventHandler);
298
+
299
+ }
300
+
301
+ }
302
+
303
+
304
+
305
+ class Disposable : IDisposable
306
+
307
+ {
308
+
309
+ protected MyObservable<TEventHandler, TEventArgs> Owner { get; private set; }
310
+
311
+ protected IObserver<TEventArgs> Observer { get; private set; }
312
+
313
+
314
+
315
+ public Disposable(MyObservable<TEventHandler, TEventArgs> owner, IObserver<TEventArgs> observer)
316
+
317
+ {
318
+
319
+ Owner = owner;
320
+
321
+ Observer = observer;
322
+
323
+ }
324
+
325
+
326
+
327
+ public void Dispose()
328
+
329
+ {
330
+
331
+ if (Owner == null) return;
332
+
333
+ Owner.RemoveObserver(Observer);
334
+
335
+ Owner = null;
336
+
337
+ }
338
+
339
+ }
340
+
341
+ }
342
+
343
+ }
344
+
345
+ ```

3

修正

2018/10/14 09:47

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -136,6 +136,6 @@
136
136
 
137
137
  そして必要な処理が終われば RemoveHandler を呼び出し、イベントハンドラを削除します。
138
138
 
139
- そして MouseMove イベントが起こるたびに Conversion から返された action を呼び出します。
139
+ そして Mouse イベントが起こるたびに Conversion から返された action を呼び出します。
140
140
 
141
141
  h は FromEvent の登録したデリゲートで、これを呼び出すことにより、以降のオブザーバーに e を渡します。

2

修正

2018/10/14 08:00

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -136,6 +136,6 @@
136
136
 
137
137
  そして必要な処理が終われば RemoveHandler を呼び出し、イベントハンドラを削除します。
138
138
 
139
- そして MouseMove イベントが起こるたびに Conversion を呼び出します。
139
+ そして MouseMove イベントが起こるたびに Conversion から返された action を呼び出します。
140
140
 
141
141
  h は FromEvent の登録したデリゲートで、これを呼び出すことにより、以降のオブザーバーに e を渡します。

1

追記

2018/10/14 07:59

投稿

Zuishin
Zuishin

スコア28660

test CHANGED
@@ -9,3 +9,133 @@
9
9
  ラムダ式については[ラムダ式っていうのが分かりません](https://teratail.com/questions/149408#reply-224905) で書いたので詳細は省略します。
10
10
 
11
11
  これでわからなければネット上に情報はたくさんありますので検索してみてください。
12
+
13
+
14
+
15
+ #追記
16
+
17
+
18
+
19
+ ラムダ式を使わず書いてみました。
20
+
21
+
22
+
23
+ ```C#
24
+
25
+ using System;
26
+
27
+ using System.Diagnostics;
28
+
29
+ using System.Reactive.Linq;
30
+
31
+ using System.Windows.Forms;
32
+
33
+
34
+
35
+ namespace WindowsFormsApp1
36
+
37
+ {
38
+
39
+ public partial class Form1 : Form
40
+
41
+ {
42
+
43
+ public Form1()
44
+
45
+ {
46
+
47
+ InitializeComponent();
48
+
49
+ }
50
+
51
+
52
+
53
+ private void button1_Click(object sender, EventArgs args)
54
+
55
+ {
56
+
57
+ Observable
58
+
59
+ .FromEvent<MouseEventHandler, MouseEventArgs>(
60
+
61
+ //h => (s, e) => h(e),
62
+
63
+ Conversion,
64
+
65
+
66
+
67
+ //h => this.MouseMove += h,
68
+
69
+ AddHandler,
70
+
71
+
72
+
73
+ //h => this.MouseMove -= h)
74
+
75
+ RemoveHandler)
76
+
77
+ .Subscribe(e =>
78
+
79
+ {
80
+
81
+ Debug.WriteLine($"({e.X},{e.Y})");
82
+
83
+ });
84
+
85
+ }
86
+
87
+
88
+
89
+ private MouseEventHandler Conversion(Action<MouseEventArgs> h)
90
+
91
+ {
92
+
93
+ void action(object s, MouseEventArgs e)
94
+
95
+ {
96
+
97
+ h(e);
98
+
99
+ }
100
+
101
+ return action;
102
+
103
+ }
104
+
105
+
106
+
107
+ private void AddHandler(MouseEventHandler h)
108
+
109
+ {
110
+
111
+ MouseMove += h;
112
+
113
+ }
114
+
115
+
116
+
117
+ private void RemoveHandler(MouseEventHandler h)
118
+
119
+ {
120
+
121
+ MouseMove -= h;
122
+
123
+ }
124
+
125
+ }
126
+
127
+ }
128
+
129
+ ```
130
+
131
+
132
+
133
+ FromEvent の引数として、Conversion, AddHandler, RemoveHandler のデリゲートを渡しています。
134
+
135
+ FromEvent はまず AddHandler を呼び出し、マウスイベントにイベントハンドラを登録します。
136
+
137
+ そして必要な処理が終われば RemoveHandler を呼び出し、イベントハンドラを削除します。
138
+
139
+ そして MouseMove イベントが起こるたびに Conversion を呼び出します。
140
+
141
+ h は FromEvent の登録したデリゲートで、これを呼び出すことにより、以降のオブザーバーに e を渡します。