Russell Bearden
Russell Bearden

Reputation: 178

Is there a better way to manage a single subscription to a changing object's event in Reactive C#?

I have a class ClassWithProperty that contains a property, SomeProperty, that is an instance of another class, ClassWithEvent, with an event, SomeEvent. The ClassWithEvent object will regularly change. I need ClassWithProperty to keep a single updated subscription to the event in ClassWithEvent.

I've come up with one way to do it so far:

public ClassWithProperty()
{
    IDisposable subscription = null;

    this
        .WhenAnyValue(x => x.SomeProperty)
        .Do(x => subscription?.Dispose())
        .Where(x => x != null)
        .Subscribe(x => subscription = 
            Observable.FromEventPattern(x, nameof(x.SomeEvent))
            .Subscribe(y => SomeMethod()));
}

This solution does work but it somehow does not feel like idiomatic Reactive code, and it also seems somewhat verbose for what I think should be a fairly typical problem to solve. Is there a better way to solve this sort of issue in Reactive?

Upvotes: 0

Views: 345

Answers (1)

Enigmativity
Enigmativity

Reputation: 117084

It's very simple with a Switch operator that switches to the latest produced inner observable of a IObservable<IObservable<T>>. It disposes of the previous subscriptions and only gives you values from the latest observable.

    IDisposable subscription =
        this
            .WhenAnyValue(x => x.SomeClass)
            .Select(x => Observable.FromEventPattern(x, nameof(x.SomeEvent)))
            .Switch()
            .Subscribe(x => SomeMethod());

If SomeClass can be null (which your original code suggests) then you can do this:

    IDisposable subscription =
        this
            .WhenAnyValue(x => x.SomeClass)
            .Select(x =>
                x == null
                    ? Observable.Never<EventPattern<object>>()
                    : Observable.FromEventPattern(x, nameof(x.SomeEvent)))
            .Switch()
            .Subscribe(x => SomeMethod());

Upvotes: 2

Related Questions