0

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;
    }
}
Gautam T Goudar
  • 271
  • 3
  • 12

1 Answers1

0

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 { }
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • This works and thank you for the reply and answer. Would you kindly let me know that why "SelectMany" works and why not "Select" in terms of executing the "Do code block"? Also, how does "SelectMany" replace the role of multiple subscribers I have in my OP? – Gautam T Goudar May 06 '18 at 03:22
  • @GautamTGoudar - Using `.Select` would return `IObservable>` so your subscription would only then subscribe to the outer observable so the inner one never gets subscribed to and hence the `.Do` doesn't run. `.SelectMany` flattens `IObservable>` into `IObservable` so then the subscriptions to the inner observables are created automatically and the `.Do` then works. – Enigmativity May 06 '18 at 03:48
  • Thank you very much for the reply. Just stretching my luck to seek more answers if possible. If I have to call 10 different objects similar to My Work() class (say MyWork1(), MyWorks2() and so on), what would be the way to do it? – Gautam T Goudar May 06 '18 at 04:12
  • @GautamTGoudar - You would create an array of delegates and use `.ToObservable()` on those before calling each in a `.SelectMany` - that's assuming that you need to call each with each `MyData` object. If you need more detail I'd suggest asking a new question. – Enigmativity May 06 '18 at 04:20
  • Posted a new question for multiple IObservable calls [here](https://stackoverflow.com/questions/50196955/rx-net-calling-multiple-iobservable-in-selectmany). I am missing something in the array of delegates and how to call in SelectMany. – Gautam T Goudar May 06 '18 at 06:46