2012-05-07 9 views
9

リアクティブエクステンションについてmsdnを読んで、Observable.Createを使用してIObservableを実装すべきではないとの勧告を見つけました...これを読んだら、私のプロジェクトはすでにObservableImplementation<T>クラスを持っていました。私はIObservableソースとして使用しましたが、どこでもObservablesにイベントを変換したいと思っていました。IObservable <T>を実装しないのはなぜですか?

私はSystem.ReactiveのAbstractObservable<T>の実装を読みましたが、コードと私の間に大きな違いは見つかりませんでした。 IObservableの実装に何が問題になりますか?私はそれに自分のプロパティを追加することができます。...

私は何か間違っていたかどうか教えてください。

public sealed class ObservableImplementation<T> : IObservable<T> 
{ 
    class Subscription : IDisposable 
    { 
     private readonly Action _onDispose; 
     public Subscription(Action onDispose) 
     { 
      _onDispose = onDispose; 
     } 

     public void Dispose() 
     { 
      _onDispose(); 
     } 
    } 


    public void Raise(T value) 
    { 
     _observers.ForEach(o => o.OnNext(value)); 
    } 
    public void Completion() 
    { 
     _observers.ForEach(o => o.OnCompleted()); 
     _observers.Clear(); 
    } 

    private readonly List<IObserver<T>> _observers = new List<IObserver<T>>(); 
    public IDisposable Subscribe(IObserver<T> observer) 
    { 
     var subscription = new Subscription(() => _observers.Remove(observer)); 
     _observers.Add(observer); 
     return subscription; 
    } 
    public bool AnyObserverPresent { get { return _observers.Any(); } } 
} 
+0

FYI、IObservable 'の具象クラスの実装がすでにあります':' Subject' –

+0

...同様に、デリゲートベースの 'IDisposable'は' Disposable.Create'を使って作成することができます –

+0

私は2番目のものを見つけましたが、置き換えを計画していますが、Subjectは単純なObservableそれは観測可能でもあるからです。いいえ? – TDaver

答えて

7

あなたがIObservable<T>を実装してはならない理由は、あなたが通常IEnumerable<T>を実装していないのと同じ理由で、誰かが最も可能性の高い、すでにあなたが望むものを構築しているということです。この場合、基本的にはSubject<T>を再実装しました。我々はIObservable <T>を実装するために人々をお勧めしません、いくつかの理由があります

var lazyObservable = Observable.Create<TFoo>(subj => { /*TODO: Implement Me to load from reflection*/ }) 
    .Multicast(new Subject<TFoo>()) // This means it'll only calc once 
    .RefCount(); // This means it won't get created until someone Subscribes 
+0

を経由してUIスレッドに取得おかげで、私はできるだけ早く怠惰なものをチェックアウトしますよん! – TDaver

21

編集:コメント欄で怠惰な質問については、私はこの方法というを実装したいです直接。

1つは、オブザーバーの文法違反からの保護の欠如です。たとえば、シーケンスが無効なOnCompleted呼び出しに続いてOnNext呼び出しの動作を示すことがあります。 Observable.Create <T>メソッドおよびObservableBase <T>ベースタイプは、ターミナルメッセージを受信すると自動的にオブザーバを切り離すことで、この処理を行います。だからあなたのコードが間違ったことをしたとしても、オブザーバーは不正なシーケンスを見ていません。

Btw、これはC#のイテレータに似ています。手動でのIEnumerable <T>を実装すると、列挙子のMoveNextメソッドは、(OnCompletedに類似)がfalseを返したとき、後続の呼び出しは(OnNextに類似した)彼らの心を変更し、trueを返し起動しないようにすべきである:

MoveNextメソッドが通過した場合コレクションの最後の列挙子は、コレクションの最後の要素の後に配置され、MoveNextはfalseを返します。列挙子がこの位置にあるとき、MoveNextへのその後の呼び出しは、Resetが呼び出されるまでfalseを返します。 (出典:MSDN)

C#2.0またはVB 11.0でイテレータを使用する場合は、このような懸念があります。これは、Observable.Create <T>メソッドを作成し、ObservableBase <T>基本タイプに似ています。

上記の説明に関連する理由は、クリーンアップです。サブスクリプションでDisposeコールから戻ると、オブザーバーはメッセージを見なくなりますか?オブザーバに端末メッセージを送信すると、関連するサブスクリプションのDisposeロジックが自動的に呼び出されますか?どちらも正しいことは自明ではないので、私たちの基本的な実装はそれを処理します。

もう1つの理由は、CurrentThreadSchedulerと関係があり、そのスケジューラで実行中にSubscribe呼び出しを非同期にできることです。基本的には、Subscribeの呼び出し中に現在のスレッドにトランポリンをインストールする必要があるかどうかを確認する必要があります。誰もがこれについて知り、正しいことをするとは思っていません。

ここで他の人が気づいたように、特定のケースでは、あなたはかなりの主題を構築しています。私たちの主題の1つを使用するか、あなた自身のタイプの封じ込めで包みます(例えば、送信側の "オブザーバー"側に受信側の "観測可能な"側以外の人がアクセスできるようにする場合)。

+0

は、誰かがイベントのような振る舞いを公開したいが、イベント発行をさせるに関連付けられたセマンティック利点とサブスクリプションを識別する「配信停止」トークンを加入者に提供する場合は何を勧めますか?私は私が私の最新の実装では、3つすべてを考えたと思うしたいと思いにもかかわらず – supercat

5

最近Rxチームのblog postには3つの理由があります。それは長い投稿ですので、私は関連する部分をコピーしました。

契約を強制

Observable.Createが得IObservable 実装に購読方法の中核 実装となるであろう単一のデリゲートを取り込みます。 他のものの中でオブザーバー契約を強制するために、このデリゲートの周りを巧みにラッピングしています(つまり、 は自分でインターフェイスを実装してはいけません)。

使い捨て

のラッパーが返さ使い捨てが 観察者がいても、処分 呼び出しから戻った後はもう呼ばれないだろうことを確認するために使用、その周りにはほとんどのラッパーを持っていますスケジューラがまだ良い停止点にないかもしれない まだ。 (あなたが手でIObservable インターフェイスを実装することはありませんさらに別の理由。ああ、方法によって、さらに多くあります!)

自動補完

にここで注目点を配置ダウンストリームのOnCompletedを送信するときにソースサブスクリプションに が適用される自動処理動作です。 (これは IObservableの手動実装が強く推奨されている理由はまだ別の理由。 Observable.Createを使用している場合、私たちはあなたのためにこれの世話をする。)

+0

おかげで、:) – TDaver

関連する問題