Max Hampton
Max Hampton

Reputation: 1304

Observable FromEventPattern when object rasing events is reinstantiated

I am trying to set up an observable in a class that will tick each time an event fires on a member.

public class FooService
{

  private BarProvider _barProvider;
  public IObservable<BarChangedEventArgs> BarChanged { get; }

  public FooService()
  {        
    BarChanged = 
      Observable
        .FromEventPattern<BarChangedHandler, BarChangedEventArgs>(
          h => _barProvider.Changed += h,
          h => _barProvider.Changed -= h)
        .Select(p => p.EventArgs);
  }

  public void OccursSomeTimeAfterFooServiceCreation
  (
    Func<BarProvider> barProviderFactory
  )
  {
    _barProvider = barProviderFactory();
  }
}

What I think I need to do is set up the event handler observable after assigning the new value of _barProvider in the OccursLater method, as this is a new event source. However, I believe setting BarChanged at this later point, after consumers may have already subscribed, will break those existing subscriptions.

I would like consumers of the FooService to be able to subscribe to BarChanged at any point, and see the observable as one stream of event args, regardless of how many times OccursSomeTimeAfterFooServiceCreation is called after the subscription is created.

Upvotes: 1

Views: 210

Answers (2)

Awesomni.Codes
Awesomni.Codes

Reputation: 2436

If your Observable - creation depends on stuff that can change e.g. your barProvider, you should always retrieve those from other Observables and then utilize the Switch() operator.

To achieve this I utilized the BehaviorSubject.

    public class FooService
    {
        public BehaviorSubject<BarProvider> _barProviderSubject = new BehaviorSubject<BarProvider>(null); //or initialize this subject with the barprovider of your choice

        public IObservable<BarChangedEventArgs> BarChanged { get; }

        public FooService()
        {
            var barChangedChanged = _barProviderSubject.Where(bP => bP != null).Select(bP =>
                Observable.FromEventPattern<BarChangedHandler, BarChangedEventArgs>(
                        h => bP.Changed += h,
                        h => bP.Changed -= h)
                    .Select(p => p.EventArgs)
            );
            BarChanged = barChangedChanged.Switch();
        }

        public void OccursSomeTimeAfterFooServiceCreation
        (
            Func<BarProvider> barProviderFactory
        )
        {
            _barProviderSubject.OnNext(barProviderFactory());
        }
    }

Upvotes: 0

Paulo Morgado
Paulo Morgado

Reputation: 14856

The problem is that you don't observe classes or variables. You observe instances.

If I understand it correctly, you want your subscribers to be oblivious of the fact that the observed instance changes.

Try something like this:

public class FooService
{
  private BarProvider _barProvider;
  private Subject<BarChangedEventArgs> subject = new Subject<BarChangedEventArgs>();
  public IObservable<BarChangedEventArgs> BarChanged { get; } = subject.AsObservable();

  public FooService()
  {        
  }

  public void OccursSomeTimeAfterFooServiceCreation
  (
    Func<BarProvider> barProviderFactory
  )
  {
    _barProvider = barProviderFactory();

    BarChanged = 
      Observable
        .FromEventPattern<BarChangedHandler, BarChangedEventArgs>(
          h => _barProvider.Changed += h,
          h => _barProvider.Changed -= h)
        .Select(p => p.EventArgs)
        .Subscribe(subject);
  }
}

Upvotes: 0

Related Questions