统计某个主题的所有订阅数

Sna*_*nak 3 c# unity-game-engine reactive-programming system.reactive observer-pattern

我有一个主题,我在其中订阅在游戏中发生确定事件时应该调用的方法。

public Subject<SomeEvent> TestSubject = new Subject<SomeEvent>();
Run Code Online (Sandbox Code Playgroud)

某些实例订阅该主题。

TestSubject.Subscribe(MyMethod);
Run Code Online (Sandbox Code Playgroud)

我的目标是计算有多少方法已订阅该主题。我见过一些使用 Count() 扩展的示例,但我需要一个 int 作为返回值,这样我就可以在其他地方使用它,并且 Count() 返回一个 IObservable。

if (subjectCount > 0)
{
    DoSomething();
}
Run Code Online (Sandbox Code Playgroud)

有没有什么方法可以获取某个主题的订阅数量,或者我是否需要手动跟踪它们(有一个 public int subjectSubcriptions 并在每次订阅方法时添加 1)?

Cha*_*ice 5

最简单的方法是使用主题的包装器创建您自己的 ISubject 实现。

public class CountSubject<T> : ISubject<T>, IDisposable
{
    private readonly ISubject<T> _baseSubject;
    private int _counter;
    private IDisposable _disposer = Disposable.Empty;
    private bool _disposed;

    public int Count
    {
        get { return _counter; }
    }

    public CountSubject()
        : this(new Subject<T>())
    {
        // Need to clear up Subject we created
        _disposer = (IDisposable) _baseSubject;
    }

    public CountSubject(ISubject<T> baseSubject)
    {
        _baseSubject = baseSubject;
    }

    public void OnCompleted()
    {
        _baseSubject.OnCompleted();
    }

    public void OnError(Exception error)
    {
        _baseSubject.OnError(error);
    }

    public void OnNext(T value)
    {
        _baseSubject.OnNext(value);
    }

    public IDisposable Subscribe(IObserver<T> observer)
    {
        Interlocked.Increment(ref _counter);
        return new CompositeDisposable(Disposable.Create(() => Interlocked.Decrement(ref _counter)),
                                       _baseSubject.Subscribe(observer));
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                _disposer.Dispose();
            }
            _disposed = true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)