如何将其转换为使用Rx而不是.net样式的事件

本文关键字:net 样式 事件 Rx 转换 | 更新日期: 2023-09-27 18:05:35

根据之前的一个问题,一个用户告诉我,我不应该公开。net event风格的API,除非绝对被迫:

如果你没有被强制这样做,不要使用c#风格的事件来创建API。

在这种情况下,我应该如何实现一个"事件",一个模型将以某种方式通知任何观察者它已经改变了?该事件预计只被调用一次。比如说,我的模型是一个Minecraft Block,我在这个模型上调用Destroy()方法。Destroy()方法应该向它的观察者广播该模型打算被销毁。观察者的例子将是一个控制器,然后将BlockDestroyed通知发送到视图(我欣赏控制器可能是一个不必要的间接级别,但是做模型->控制器->视图比模型(可观察对象)->视图(观察者)容易得多)。

下面是我的代码,我打算将其更改为Rx样式-记住,Destroyed将只在每个块中调用一次-并且可能存在其他事件,例如Damaged, ActivatedTextureChanged

public class Block
{
    public Block()
    {
    }
    /// <summary>
    /// Destroy the block.
    /// </summary>
    public void Destroy()
    {
        var msg = new BlockDestroyedMessage();
        if (Destroyed != null)
            Destroyed(this, msg);
    }
    public event EventHandler<BlockDestroyedMessage> Destroyed;
}

还请注意,我在网上看到的文档基本上是

  • 应该避免ISubject<T>,因为它鼓励违反SRP(我同意)
  • 不要实现IObservable<T>(因为有太多的工厂方法来创建可观察对象)

如何将其转换为使用Rx而不是.net样式的事件

我会这样做:

public class Block
{
    public void Destroy()
    {
        if (_destroyed != null)
        {
            var msg = new BlockDestroyedMessage();
            _destroyed.OnNext(msg);
            _destroyed.OnCompleted();
            _destroyed = null;
        }
    }
    private Subject<BlockDestroyedMessage> _destroyed
        = new Subject<BlockDestroyedMessage>();
    public readonly IObservable<BlockDestroyedMessage> Destroyed
        = _destroyed.AsObservable();
}