[英]How to get the count of items in an observable stream without maintaining state yourself?
如何使用Rx習語在任何給定的時間點獲得這所學校的學生人數,而不必自己保持School
班級的狀態?
using System;
using System.Reactive.Subjects;
namespace SchoolManagementSystem
{
public class School
{
private ISubject<Student> _subject = null;
private int _maxNumberOfSeats;
private int _numberOfStudentsAdmitted;
public string Name { get; set; }
public School(string name, int maxNumberOfSeats)
{
Name = name;
_maxNumberOfSeats = maxNumberOfSeats;
_numberOfStudentsAdmitted = 0;
_subject = new ReplaySubject<Student>();
}
public void AdmitStudent(Student student)
{
try
{
if (student == null)
throw new ArgumentNullException("student");
if (_numberOfStudentsAdmitted == _maxNumberOfSeats)
{
_subject.OnCompleted();
}
// Obviously can't do this because this will
// create a kind of dead lock in that it will
// wait for the _subject to complete, but I am
// using the same _subject to issue notifications.
// _numberOfStudentsAdmitted = _subject.Count().Wait();
// OR to keep track of state myself
Interlocked.Increment(ref _numberOfStudentsAdmitted);
_subject?.OnNext(student);
}
catch(Exception ex)
{
_subject.OnError(ex);
}
}
public IObservable<Student> Students
{
get
{
return _subject;
}
}
}
}
還是這與使用Rx設計的組件原理不協調?
這是客戶端應該負責的事情(獲取計數並在onNext
處理程序中產生所有副作用)嗎? 並且可觀察對象應該僅充當無狀態信號源或門,就像硬件中斷例程那樣,簡單地向CPU發出感興趣的信號嗎?
在那種情況下,我們失去了可觀察到的信號完成標准。 那么應該如何知道何時完成?
您可以在_subject
序列上使用Count()方法。 它將自己創建一個可觀察的序列,其中產生的每個值代表_subject
最新的學生_subject
。
然后,您可以對這個學生計數值序列進行反應。 Zip()操作在這方面可能很有用,因為它的優點是當其內部序列中的任何一個完成時,可以完成結果序列,您可以使用TakeWhile強制執行該操作 。
結果看起來像這樣
Observable.Zip(
_subject.Select(student => != null ? student ? throw new ArgumentNullException("student")),
_subject.Count().TakeWhile(studentCount => studentCount < _maxNumberOfSeats),
(student, count) => student
);
在AdmitStudent
方法主體中剩下要做的就是簡單地用_subject?.OnNext(student)
將任何新學生推入序列(就像您已經做過的那樣),但是沒有額外的邏輯。 您還可以對此進行一些修改,以確保_subject
本身也能在達到最大學生人數后完成,但是我不確定您的業務規則,因此我_subject
您自己決定。
我可以建議的最后一件事是,如果要使用Rx類型的擴展名,並看看這個網站的使用情況,該網站會大量使用它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.