Ada IObservable dan IObserver interface di NET (juga di sini dan di sini ). Menariknya, implementasi konkret dari IObserver tidak memiliki referensi langsung ke IObservable. Tidak tahu dengan siapa berlangganannya. Itu hanya dapat memanggil unsubscriber. "Silakan tarik pin untuk berhenti berlangganan."
edit: The unsubscriber mengimplementasikan IDisposable
. Saya pikir, skema ini digunakan untuk mencegah masalah pendengar yang murtad .
Namun, ada dua hal yang tidak sepenuhnya jelas bagi saya.
- Apakah kelas Unsubscriber dalam menyediakan perilaku berlangganan dan lupa? Siapa (dan kapan tepatnya) memanggil
IDisposable.Dispose()
Unsubscriber? Pengumpul sampah (GC) tidak deterministik.
[Penafian: secara keseluruhan, saya menghabiskan lebih banyak waktu dengan C dan C ++ daripada dengan C #.] Apa yang harus terjadi jika saya ingin berlangganan pengamat K ke L1 yang dapat diamati dan pengamat sudah berlangganan beberapa L2 yang dapat diamati?
K.Subscribe(L1); K.Subscribe(L2); K.Unsubscribe(); L1.PublishObservation(1003); L2.PublishObservation(1004);
Ketika saya menjalankan kode tes ini terhadap contoh MSDN, pengamat tetap berlangganan L1. Ini akan menjadi khas dalam pengembangan nyata. Secara potensial, ada 3 jalan untuk meningkatkan ini:
- Jika pengamat sudah memiliki contoh unsubscriber (yaitu sudah berlangganan), maka diam-diam berhenti berlangganan dari penyedia asli sebelum berlangganan yang baru. Pendekatan ini menyembunyikan fakta bahwa itu tidak lagi berlangganan ke penyedia asli, yang mungkin akan mengejutkan nanti.
- Jika pengamat sudah memiliki contoh unsubscriber, maka dilemparkan pengecualian. Kode panggilan yang baik harus berhenti berlangganan pengamat secara eksplisit.
- Pengamat berlangganan beberapa penyedia. Ini adalah opsi yang paling menarik, tetapi bisakah ini diimplementasikan dengan IObservable dan IObserver? Ayo lihat. Adalah mungkin bagi pengamat untuk menyimpan daftar objek unsubscriber: satu untuk setiap sumber. Sayangnya,
IObserver.OnComplete()
tidak memberikan referensi kembali ke penyedia yang telah mengirimnya. Jadi, implementasi IObserver dengan beberapa penyedia tidak akan dapat menentukan dari yang berlangganan.
Apakah .NET IObserver dimaksudkan untuk berlangganan beberapa IObservables?
Apakah definisi buku teks dari pola pengamat mensyaratkan bahwa satu pengamat harus dapat berlangganan ke beberapa penyedia? Atau apakah itu opsional dan tergantung pada implementasi?
sumber
using
blok. Biaya untuk pernyataan berlangganan harus hampir nol, sehingga Anda akan neter blok menggunakan, berlangganan, meninggalkan blok menggunakan (sehingga berhenti berlangganan) membuat kode agak tidak bergunaKamu benar. Contoh ini bekerja buruk untuk beberapa IObservables.
Saya kira OnComplete () tidak memberikan referensi kembali karena mereka tidak ingin IObservable harus menyimpannya. Jika saya menulis bahwa saya mungkin akan mendukung beberapa langganan dengan meminta Langganan mengambil pengidentifikasi sebagai parameter kedua, yang akan diteruskan kembali ke panggilan OnComplete (). Jadi bisa dibilang begitu
Seperti berdiri, tampaknya. NET IObserver tidak cocok untuk banyak pengamat. Tapi saya kira objek utama Anda (LocationReporter dalam contoh) bisa
dan itu akan memungkinkan Anda untuk mendukung
demikian juga.
Saya kira Microsoft dapat berargumen bahwa oleh karena itu tidak perlu bagi mereka untuk secara langsung mendukung beberapa IObservables di antarmuka.
sumber
IObserver.OnComplete()
tidak mengidentifikasi dari siapa panggilan itu berasal. Jika pengamat berlangganan lebih dari satu yang dapat diamati, maka tidak tahu dari siapa harus berhenti berlangganan. Antiklimaks. Saya bertanya-tanya, apakah .NET memiliki antarmuka yang lebih baik untuk pola pengamat?Observable.Create()
untuk membangun yang diamati, dan merantai beberapa sumber yang dapat diamati menggunakan ituSubscribe()
. Saya secara tidak sengaja melewati pengamatan yang dapat diamati dalam satu jalur kode. Ini melengkapi pengamatan saya yang baru dibuat, meskipun sumber-sumber lain tidak lengkap. Butuh waktu lama untuk bekerja di luar apa yang perlu saya lakukan - saklarObservable.Empty()
untukObservable.Never()
.Saya tahu ini adalah cara terlambat ke pesta, tapi ...
Antarmuka saya
Observable<T>
danIObserver<T>
yang tidak bagian dari Rx ... mereka jenis inti sedang ... tapi Rx membuat ekstensif menggunakan mereka.Anda bebas untuk memiliki sebanyak (atau sesedikit) pengamat sesuka Anda. Jika Anda mengantisipasi beberapa pengamat, adalah tanggung jawab yang dapat diamati untuk merutekan
OnNext()
panggilan ke pengamat yang tepat untuk setiap peristiwa yang diamati. Yang diamati mungkin memerlukan daftar atau kamus seperti yang Anda sarankan.Ada beberapa kasus yang baik untuk memungkinkan hanya satu - dan kasus yang baik untuk memungkinkan banyak. Misalnya, dalam implementasi CQRS / ES, Anda mungkin menerapkan penangan perintah tunggal per jenis perintah pada bus perintah, sementara Anda mungkin memberi tahu beberapa transformasi sisi-baca untuk peristiwa tertentu jenis di toko peristiwa.
Sebagaimana dinyatakan dalam jawaban lain, tidak ada
Unsubscribe
. Membuang benda yang Anda berikan saatSubscribe
umumnya melakukan pekerjaan kotor. Pengamat, atau agennya, bertanggung jawab untuk memegang token sampai tidak lagi ingin menerima pemberitahuan lebih lanjut . (pertanyaan 1)Jadi, dalam contoh Anda:
... akan lebih seperti:
... di mana K akan mendengar 1003 dan 1004 tetapi tidak 1005.
Bagi saya, ini masih terlihat lucu karena secara nominal, berlangganan adalah hal yang berumur panjang ... sering selama durasi program. Mereka tidak berbeda dalam hal ini dengan acara .Net normal.
Dalam banyak contoh yang saya lihat,
Dispose
token tidak bekerja untuk menghilangkan pengamat dari daftar pengamat yang diamati. Saya lebih suka bahwa token tidak membawa begitu banyak pengetahuan di sekitar ... dan jadi saya telah menggeneralisasi token berlangganan saya hanya memanggil lambda yang lewat (dengan mengidentifikasi informasi yang ditangkap pada waktu berlangganan:... dan yang dapat diamati dapat menginstal perilaku berhenti berlangganan selama berlangganan:
Jika pengamat Anda menangkap peristiwa dari beberapa yang dapat diamati, Anda mungkin ingin memastikan bahwa ada semacam informasi korelasi dalam acara itu sendiri ... seperti .Net
sender
. Terserah Anda apakah itu penting atau tidak. Itu tidak dipanggang, seperti yang Anda alasankan dengan benar. (pertanyaan 3)sumber