I have a third party API that I do not have the source to. I instantiate a callback to an event like this:
using namespace API; // This is where APIClient lives
namespace TestApiClientUI
{
public partial class Form1 : Form
{
APIClient apiClient = new APICLient();
apiClient.QuoteUpdated += api_ClientUpdated;
private void api_ClientUpdated(object sender, string s, double b, double a)
{
}
}
}
How do I wrap this into an Rx Observable.FromEvent?
Also, is there a way to do it so the overhead of the wraps copy are as little (zero-copy) as possible?
Let's define a struct to store the event args.
Now we can define an
IObservable<QuoteUpdate>
as follows.The first lambda defines a mapping from
Action<QuoteUpdate>
toApiQuoteHandler
. The action, calledemit
, is what actually broadcasts a value to the subscribers of the observable we are defining. Think of callingemit(value);
as something likeforeach (var subscriber in subscribers) { subscriber.OnNext(value); }
.The reason we need this first mapping is because the actual underlying event only knows how to subscribe and unsubscribe
ApiQuoteHandler
instances. The second and third lambdas are of typeAction<ApiQuoteHandler
. They are called on subscription and unsubscription, respectively.When an
IObserver<QuoteUpdate> observer
subscribes to theIObservable<QuoteUpdate>
we have defined, this is what happens:observer.OnNext
(of typeAction<QuoteUpdate>
) is passed into our first lambda as the variableemit
. This creates anApiQuoteHandler
that wraps theobserver
.ApiQuoteHandler
is then passed into our second lambda as the variablehandler
. Thehandler
subscribes to theQuoteUpdated
event on yourapiClient
.IDisposable
returned fromSubscribe
method on ourIObservable<QuoteUpdate>
contains a reference to theApiQuoteHandler
that was created by the first of our three lambdas.IDisposable
is disposed, the third lambda is called with the sameApiQuoteHandler
from before, unsubscribing from the underlying event.Because you need a single
IObservable<T>
for someT
yet you have event args(s, b, a)
, you must define some struct or class to store the three values. I would not worry about the cost of copying astring
reference and twodouble
values.