2

I have a User model that has an IObservable<int> property. This property is backed by a BehaviorSubject that is initialized with a certain value. How can I get the current value of the observable, without having to expose another property that accesses the .Value property on the underlying BehaviorSubject?

This is the sample model to consider:

class User
{
    private readonly BehaviorSubject<int> mySubject;

    public User()
    {
        mySubject = new BehaviorSubject<int>(100);
    }

    public IObservable<int> Value => mySubject.DistinctUntilChanged();

    public void SomeMethod(int level)
    {
        mySubject.OnNext(level);
    }
}

Notice that I have a method that calls OnNext on the subject with the specified value. This is already strange to me, it would be better if I could just treat the Value observable as a get and set property but alas...

On another part of my code, I need to imperatively get the current value for a given user, and I can't seem to find a way to do that from the IObservable interface directly. I tried using both the Latest and MostRecent methods, but they seem to do different things than what I would expect. When trying both, my application blocks indefinitely.

The only way I found to properly expose the value was to create another property for the "current" value, like this:

public int CurrentValue => mySubject.Value;

I don't like this because it feels to me that I'm being redundant. Is there a better way to expose the current value of the observable so that external code can just get the value and do what it wants with it? For that matter, as I commented earlier, I'm also not very happy having another method to mutate the value. It makes the interface of the object cumbersome in my view. In knockoutjs for instance, I can get and set the value just by "calling" the observable, which seems simpler. In this case this would be equivalent to Value().

julealgon
  • 7,072
  • 3
  • 32
  • 77

1 Answers1

3

You can always do one of these, depending on whether you're in an async context or not:

var value = await user.Value.FirstAsync();
var value = user.Value.First();

Alternatively, you can do something like this:

class User
{
    private readonly BehaviorSubject<int> valueSubject;
    public int Value
    {
        get { return valueSubject.Value; }
        set { valueSubject.OnNext(value); }
    }
    public IObservable<int> ValueChanged => valueSubject.DistinctUntilChanged();

    public User()
    {
        valueSubject = new BehaviorSubject<int>(100);
    }
}
Timothy Shields
  • 75,459
  • 18
  • 120
  • 173