Gautam T Goudar
Gautam T Goudar

Reputation: 381

Rx.Net: Chaining subscribers - alternative approach?

How can I re-write this code so that I don't have to chain Subscribers like below? Reason for asking is, this style will limit in an observable depending on another observable due to the style of the code, it can get confusing.

var results = myService
          .GetData(accountId)    // returns IObservable
          .Subscribe(data =>
          {
              new MyWork().Execute(data)  // returns IObservable
                  .Subscribe(result =>
                  {
                      myResults.Add(result);
                      WriteLine($"Result Id: {result.Id}");
                      WriteLine($"Result Status: {result.Pass}");
                  });
          }); 

Added after 1st reply from Peter Bons

Below is the code for MyWork class that has the Execute Method

public class MyWork 
{
    public virtual IObservable<MyResult> Execute(MyData data)
    {
        MyResult result = null;

        return IsMatch(data)
            .Do(isMatch =>
            {
                if (isMatch)
                {
                    result = new MyResult(1, true);
                }
            })
            .Select(_ => result);
    }


    public IObservable<bool> IsMatch(MyData data)
    {
        return true;
    }
}

Upvotes: 0

Views: 537

Answers (1)

Enigmativity
Enigmativity

Reputation: 117027

It's really quite simple.

var results =
    myService
      .GetData(accountId)
      .SelectMany(data => new MyWork().Execute(data))
      .Subscribe(result =>
      {
          myResults.Add(result);
          Console.WriteLine($"Result Id: {result.Id}");
          Console.WriteLine($"Result Status: {result.Pass}");
      });

If ever you are subscribing within a subscription then you are doing something wrong. Keep that in mind. There is almost always a way to make it a pure query with a single subscription.

Just to help out with testing, here's the code required to make this a Minimal, Complete, and Verifiable example.

public static class myService
{
    public static IObservable<MyData> GetData(int x)
        => Observable.Return(new MyData());
}

public class MyWork 
{
    public virtual IObservable<MyResult> Execute(MyData data)
    {
        MyResult result = null;

        return IsMatch(data)
            .Do(isMatch =>
            {
                if (isMatch)
                {
                    result = new MyResult() { Id = 1, Pass = true};
                }
            })
            .Select(_ => result);
    }


    public IObservable<bool> IsMatch(MyData data)
    {
        return Observable.Return(true);
    }
}

public class MyResult
{
    public int Id;
    public bool Pass;
}

public class MyData { }

Upvotes: 0

Related Questions