1

IObservable<T>次のSubscribe実装を検討してください。

public IDisposable Subscribe(IObserver<T> observer)
{
    if (observer == null)
    {
        throw new ArgumentNullException("observer");
    }

    lock (_subscriberSync)
    {
        var accepted = OnSubscribing(observer);   // <------ policy can be applied here

        if (!accepted)
        {
            /* #1 */ return null;
            /* #2 */ // return NullSubscription.Instance;
            /* #3 */ // throw new SubscriptionRejectedException("reason");
        }

        // ... perform actual subscription went here
    }
}

拒否されたサブスクリプションを確立する方法についてのガイダンスはないようです。理想的には、条件を表すBoolean TrySubscribe(IObserver<T> observer, out IDisposable subscription)orMaybe<IDisposable> Subscribe(IObserver<T> observer)が必要ですが、フラグ値または帯域外例外のオプションしかないようです。それぞれに欠点があります。

#1では、私が遭遇したすべてのコードがnullをチェックしていないようで、Resharperの静的分析でさえNotNull属性を設定しています。

#2ではNullSubscription、あまり発見できないことを除いて、#1と大差ないaをテストする必要があります(「魔法の」戻り値で典型的です)。

#3では、例外的な状況の典型的なフローがありますが、遅延サブスクリプションの場合、デバッグが複雑になります。

これらの 3 つの方法以外に実装されている方法はありますか?

4

2 に答える 2

2

何が問題なのobserver.onError(new SomeException())ですか?

また、に対して推奨IObservable<T>されるを手動で実装しているようです。ただし、必要な場合は、次のようにすることができます。

    public IDisposable Subscribe(IObserver<T> observer)
    {
        lock (_subscriberSync)
        {
            var accepted = OnSubscribing(observer);   // <------ policy can be applied here

            if (!accepted)
            {
                observer.OnError(new SubscriptionRejectedException("reason"));
                return Disposable.Empty;
            }

            // ... perform actual subscription went here
        }
    }
于 2013-03-12T14:42:21.797 に答える
0

実装するのに十分な理由があると思いますIObservable<T>ので、それについて詳しく説明します。質問を正しく読んだら、「サブスクリプションの失敗」がうまく溶け込んだ場合に何を返すかを知りたいと思います。チェーンされたRxクエリロジックの残りの部分で...うーん...まあ、私はおそらく次のDisposable.Create方法を使用します:

public class MyObservable<T> : IObservable<T>
{
    private static object _subscriberSync = new object();
    private IObservable<T> _source;

    public MyObservable(IObservable<T> source)
    {
        _source = source;
    }

    protected virtual bool OnSubscribing(IObserver<T> obs)
    {
        return false;
    }

    public void DohSubscriptionFailed()
    {
        // Whatever the heck you want to do here?
        Console.WriteLine("Sorry, you never got a subscription");
    }

    public IDisposable Subscribe(IObserver<T> observer)
    {
        if (observer == null)
        {
            throw new ArgumentNullException("observer");
        }

        lock (_subscriberSync)
        {
            var accepted = OnSubscribing(observer);   // <------ policy can be applied here

            if (!accepted)
            {
                return Disposable.Create(() => DohSubscriptionFailed());
            }

            // ... perform actual subscription went here
            return _source.Subscribe(observer);
        }
    }
}

使用法と出力:

void Main()
{
    // A faked up source
    var source = new Subject<bool>();

    var query = new MyObservable<bool>(source);
    using(query.Subscribe(Console.WriteLine))
    {
        // nothing on output...
        source.OnNext(true);
        // still nothing on output...
        source.OnNext(false);
        Console.ReadLine();
    }
    // dispose fires, outputs "Sorry, you never got a subscription"
}

さて、ここに書かれているように、DohSubscriptionFailedは何も役に立ちませんが、ユースケース全体に応じて、そこで必要なものをトリガーすることができます。

于 2013-03-13T15:55:04.063 に答える