1

У меня есть тема, в которой я подписываюсь на методы, которые должны вызываться, когда происходит определенное событие в игре.Подсчитайте все подписки на предмет

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

Некоторые экземпляры подписываются на эту тему.

TestSubject.Subscribe(MyMethod); 

Моя цель - подсчитать, сколько методов было подписано на этот предмет. Я видел несколько примеров с использованием расширения Count(), но мне нужно значение int как возвращаемое значение, поэтому я могу использовать его где-то еще, а Count() возвращает IObservable.

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

Есть ли способ, чтобы получить число подписок на тему или мне нужно, чтобы следить за ними вручную (Общедоступный Int 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

@ Энигматичность хорошая точка. Я обновил код. – 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