1

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

public Subject<SomeEvent> TestSubject = new Subject<SomeEvent>(); 

某些实例订阅该主题。

TestSubject.Subscribe(MyMethod); 

我的目标是计算已订阅该主题的方法数。我见过一些使用Count()扩展的例子,但是我需要一个int作为返回值,所以我可以在其他地方使用它,而Count()返回一个IObservable。

if (subjectCount > 0) 
{ 
    DoSomething(); 
} 

有没有什么办法让一个主题订阅的数量还是需要手动跟踪它们(具有公众诠释SubjectSubcriptions并添加1次每次我订阅的方法)?

回答

3

最简单的方法是创建你自己的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; 
     } 
    } 
} 
+0

看起来像一个很好和干净的解决方案,在接受这个答案之前会等待一些其他解决方案。谢谢 ! – Snak

+1

这不是一个坏的解决方案,但'Subject '是一次性的,所以这个实现也应该是'IDisposable>',它应该支持处理至少创建的主题。 – Enigmativity

+0

@Enigmativity好点。我更新了代码。 – CharlesNRice

0

我很好奇这是否仅用于测试目的。如果是这样,那么Rx-Testing nuget软件包中有工具可以为您提供这些信息。

例如你可以在这样的单元测试中验证订阅的数量

TestScheduler scheduler = new TestScheduler(); 
var obs = scheduler.CreateColdObservable(
     ReactiveTest.OnNext(1, "foo"), 
     ReactiveTest.OnNext(1000, "bar"), 
    ); 

//Do some work that should add subscriptions. 
Assert.AreEqual(expectedSubriptionCount, obs.Subscriptions); 
+0

不是测试目的,它是游戏需要的。感谢你的回答。 – Snak