【RxMvvmLight】0x0A 简易 MessageBus
MessageBus
在 MVVM 模式里,MessageBus 是一个兜底的东西,虽然我觉得这就是一个大号 goto,能不用就不用,但有些需求吧,不用它就得写好长的代码,所以这里还是有必要做一个的。
鉴于我已经有了丰富的 Dispose 操作符可以管理订阅,而且框架里到处都是强引用订阅,我这里就不考虑使用弱引用了,这样更一致。
订阅需要记得用 DisposeWithXXX 系列方法释放,不然会内存泄漏。
所以这个东西没啥好说的,直接看代码吧:
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
public sealed class MessageBus
{
private MessageBus(){}
public static readonly MessageBus Instance = new();
public void Publish<TMessage>(TMessage message) => MessageBus<TMessage>.Instance.Publish(message);
public IDisposable Subscribe<TMessage>(Action<TMessage> handler) => MessageBus<TMessage>.Instance.Subscribe(handler);
}
internal class MessageBus<TMessage>
{
public static readonly MessageBus<TMessage> Instance = new();
readonly Lock _gate = new();
readonly List<Action<TMessage>> list = [];
public void Publish(TMessage message)
{
List<Action<TMessage>> snapshot;
lock (_gate)
snapshot = [.. list];
foreach (var sub in snapshot)
{
sub.Invoke(message);
}
}
public IDisposable Subscribe(Action<TMessage> handler)
{
ArgumentNullException.ThrowIfNull(handler);
lock (_gate)
list.Add(handler);
return Disposable.Create(() =>
{
lock (_gate)
list.Remove(handler);
});
}
}
MessageBus 类型是单例类,这允许编写扩展方法。
这基本就是个带参数版本的 AsyncSignal,不过这里是纯同步的,因为我不想让消息通知变得太重,他应该就起一个传递信号的作用,如果有其他作用的话,建议用 AsyncSignal,虽然我没做带参数的版本hhh。
然后再学生命周期,加几个成套的扩展, 就齐活了:
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
public static class MessageBusExtensions
{
extension(MessageBus self)
{
public IDisposable SubscribeOnce<TMessage>(Action<TMessage> handler, Predicate<TMessage>? predicate = null)
{
IDisposable? disposable = null;
disposable = MessageBus.Instance.Subscribe<TMessage>(message =>
{
if (predicate is null || predicate(message))
{
disposable?.Dispose();
handler(message);
}
});
return disposable;
}
}
extension(IDisposable self)
{
public IDisposable DisposeWithMessage<TMessage>(Predicate<TMessage>? predicate = null)
{
MessageBus.Instance.SubscribeOnce(_ =>
{
self.Dispose();
}, predicate);
return self;
}
}
extension(IAsyncDisposable self)
{
public IAsyncDisposable DisposeWithMessage<TMessage>(Predicate<TMessage>? predicate = null)
{
MessageBus.Instance.SubscribeOnce(_ =>
{
self.DisposeAsync();
}, predicate);
return self;
}
}
}
本文由作者按照 CC BY 4.0 进行授权