EventHandler 与 Rx 主题
Posted
技术标签:
【中文标题】EventHandler 与 Rx 主题【英文标题】:EventHandler vs Rx Subject 【发布时间】:2022-01-12 08:08:44 【问题描述】:我正在使用System.Reactive
,但我不知道该选择哪一个:EventHandlers 或 Subjects。它们有什么区别?
var client = WebSocketClient.Create(uri);
// Subject
client.OnConnected
.Subscribe(_ => Log.Information($"Socket client.Id connected"); )
.DisposeWith(disposable);
// EventHandler
Observable
.FromEventPattern(h => client.Connected += h, h => client.Connected -= h)
.Select(_ => Unit.Default)
.Subscribe(_ => Log.Information($"Socket client.Id connected"); )
.DisposeWith(disposable);
public class WebSocketClient : IWebSocketClient
// Subject
private readonly ISubject<Unit> _connectedSubject = new Subject<Unit>();
public IObservable<Unit> OnConnected => _connectedSubject.AsObservable();
// EventHandler
private EventHandler? _connected;
public event EventHandler Connected
add => _connected += value;
remove => _connected -= value;
// Logic
async Task IWebSocketClient.ConnectAsync(CancellationToken cancellationToken)
...
await _webSocket.ConnectAsync(_uri, cancellationToken).ConfigureAwait(false);
_connected?.Invoke(this, EventArgs.Empty);
_connectedSubject.OnNext();
...
private void Dispose()
_connectedSubject.OnCompleted();
【问题讨论】:
【参考方案1】:这是一个示例代码,可以更好地说明使用主题而不是事件来创建可观察对象。
public class Foo
private event EventHandler<Unit> _bang;
public IObservable<Unit> Bangs =>
Observable
.FromEventPattern<Unit>(h => _bang += h, h => _bang -= h)
.Select(x => x.EventArgs);
private Subject<Unit> _boom = new Subject<Unit>();
public IObservable<Unit> Booms =>
_boom.AsObservable();
public void OnExplode()
_bang?.Invoke(this, Unit.Default);
_boom.OnNext(Unit.Default);
现在我可以执行它了:
var foo = new Foo();
foo.Bangs.Subscribe(_ => Console.WriteLine("Bang!"));
foo.Booms.Subscribe(_ => Console.WriteLine("Boom!"));
foo.OnExplode();
我在控制台上得到的结果是这样的:
Bang!
Boom!
代码做得很好。
现在,这两种方法的关注点是Foo
类的邪恶编码器。他们可以添加这个方法:
public void Nefarious()
_boom.OnCompleted();
_bang = null;
这有效地杀死了代码。
现在我可以运行这个了:
var foo = new Foo();
foo.Bangs.Subscribe(_ => Console.WriteLine("Bang!"));
foo.Booms.Subscribe(_ => Console.WriteLine("Boom!"));
foo.OnExplode();
foo.Nefarious();
foo.OnExplode();
而且我仍然只会看到一次输出。
两者都可能损坏。
不过,总的来说,我发现很少有人将他们的事件代表设置为 null
。
主题很可能会结束或出错,从而停止代码表单的工作。
【讨论】:
以上是关于EventHandler 与 Rx 主题的主要内容,如果未能解决你的问题,请参考以下文章
Java中完美实现C#的EventHandler事件模式,代码优雅解耦合
IWebBrowser2 OnBeforeNavigate 事件 - EventHandler
[Vue-rx] Access Events from Vue.js Templates as RxJS Streams with domStreams