Here's what I mean. Suppose I'm working with an API that exposes events, but these events do not follow the standard EventHandler
or EventHandler<TEventArgs>
signature. One event might look like this, for instance:
Public Event Update(ByVal sender As BaseSubscription, ByVal e As BaseEvent)
Now, typically, if I want to get an IObservable<TEventArgs>
from an event, I can just do this:
Dim updates = Observable.FromEvent(Of UpdateEventArgs)( _
target:=updateSource, _
eventName:="Update" _
)
But this doesn't work, because the Update
event is not an EventHandler<UpdateEventArgs>
-- in fact, there is no UpdateEventArgs
-- it's basically just its own thing.
Obviously, I could define my own class deriving from EventArgs
(i.e., UpdateEventArgs
), write another class to wrap the object providing the Update
event, give the wrapper class its own Update
event that is an EventHandler<UpdateEventArgs>
, and get an IObservable<UpdateEventArgs>
from that. But that's an annoying amount of work.
Is there some way to create an IObservable<[something]>
from a "non-standard" event like this, or am I out of luck?
UPDATE: From Jon Skeet's answer, I'm nudged in the direction of the following overload of Observable.FromEvent
:
Function FromEvent(Of TDelegate, TEventArgs As EventArgs)( _
conversion As Func(Of EventHandler(Of TEventArgs), TDelegate), _
addHandler As Action(Of TDelegate), _
removeHandler As Action(Of TDelegate) _
) As IObservable(Of IEvent(Of TEventArgs))
I have to admit, though, I'm having trouble wrapping my head around that Func(Of EventHandler(Of TEventArgs), TDelegate)
part. It seems backwards to me (?). Obviously, there's just something I'm missing...
Anyway, in case it helps, I think this is what the equivalent C# code would look like (I'll be perfectly honest: I'm not sure about this. Even though I generally prefer C# myself, this code is the work of one of my colleagues, who writes primarily in VB.NET; and VB.NET permits multiple syntaxes for declaring events):
// notice: not an EventHandler<TEventArgs>
public delegate void UpdateEventHandler(BaseSubscription sender, BaseEvent e);
// not 100% sure why he did it this way
public event UpdateEventHandler Update;
The tricky part here is that it seems that some kind of class deriving from EventArgs
is necessary, no matter what. In the API I'm working with, there is no such class. So, bare minimum, I'll have to write one. But that should be fairly trivial (basically one property: BaseEvent
).
In the end, I'm assuming the code required for this overload would look something like this in C#:
var updates = Observable.FromEvent<UpdateEventHandler, UpdateEventArgs>(
// conversion (Func<EventHandler<UpdateEventArgs>, UpdateEventHandler>)
handler => (sender, e) => handler(sender, new UpdateEventArgs(e)),
// addHandler (Action<UpdateEventHandler>)
handler => updateSource.Update += handler,
// removeHandler (Action<UpdateEventHandler>)
handler => updateSource.Update -= handler
);
First of all: do I even have this straight? Second of all: am I correct in saying that using VB 9, there's really no way to accomplish the above without writing my own methods?
It almost feels to me like I'm approaching this problem from the entirely wrong angle to begin with. But I'm really not sure.