Search code examples
c#system.reactive

How to loop through an IObservable containing an IEnumerable in C#?


I am trying to get a list of paired bluetooth devices using C#, the method used returns an IObservable collection containing IEnumerable objects which contain Bluetooth Device objects. The compiler marks the variable assigned the return type of this method as IObservable<IEnumerable<IDevice>>. I am trying to access the IDevice from the collection. The documentation of the method suggests the use of a Subscribe() method to iterate through the collection but I do not know if this Subscribe() method needs some external trigger

List<string> devNames= new List<string>();
//I have tested the line below and it returns true so its not a permission issue
if (adapter.CanViewPairedDevices())
{
//here is my device collection variable
IObservable<IEnumerable<IDevice>> devices =adapter.GetConnectedDevices();
//here is how I try to get device names from the above collection
devices.Subscribe(deviceResult =>
       {
         foreach(var device in deviceResult){
                        devNames.Add(device.Name);
                                            }
       });
}
//devNames is still empty at this point

My list of names is empty at the end of the method call, does Subscribe need some kind of trigger ? Is there an alternative way of iterating through such a type that will result in names being added to the list?


Solution

  • What you want is this:

    IList<string> devNames =
        adapter
            .GetConnectedDevices()
            .SelectMany(devices => devices.Select(device => device.Name))
            .ToList()
            .Wait();
    

    That will block on the observable which may not be desirable, so you can also await this code and make it asynchronous. Try this:

    IList<string> devNames = await
        adapter
            .GetConnectedDevices()
            .SelectMany(devices => devices.Select(device => device.Name))
            .ToList();
    

    You could use .Subscribe(...) but you wouldn't populate the List<string> devNames in the subscription. Using Rx, like I have above, you end up with an observable returns your IList<string>, so in the subscription you would need to know what you want to do with the list. You haven't said that in the question, so I can't answer that.