60

We've got a client calling off to a TIBCO EMS queue and are wiring up the events like this:

var msgConsumer = _session.CreateConsumer(responseQueue);
var response = Observable.FromEvent<EMSMessageHandler,EMSMessageEventArgs>
            (h => msgConsumer.MessageHandler += h, h => msgConsumer.MessageHandler -= h)
            .Where(arg => arg.Message.CorrelationID == message.MessageID);

When I call response.Subscribe(...) I get System.ArgumentException "Error binding to target method."

I can make it work with Observable.FromEventPattern<EMSMessageEventArgs>(msgConsumer, "MessageHandler") but then it's got the event as a string and just not as clean.

Also I have IObservable<EventPattern<EMSMessageEventArgs>> rather than IObservable<EMSMessageEventArgs>

What I'd like to understand is: when should I use FromEvent over FromEventPattern? It seems a bit trial and error.

baralong
  • 1,644
  • 1
  • 16
  • 32
  • 1
    There are other overloads of FromEventPattern which do not have a string parameter if that's what you are concerned about. – Richard Anthony Hein Jun 24 '11 at 14:11
  • Thanks, I'd missed that overload. Yes the string did bother me, but it was more the difference between my FromEvent and FromEventPattern (see comment on your answer below) – baralong Jun 27 '11 at 01:23
  • See http://stackoverflow.com/questions/19895373/how-to-use-observable-fromevent-instead-of-fromeventpattern-and-avoid-string-lit for a full explanation of FromEvent too. – James World Nov 05 '14 at 02:57

3 Answers3

74

"Use FromEvent for events structurally don't look like a .NET event pattern (i.e. not based on sender, event args), and use FromEventPattern for the pattern-based ones." - Bart De Smet (Rx team)

Richard Anthony Hein
  • 10,550
  • 3
  • 42
  • 62
  • 13
    Thanks, I had found that comment but I think I misunderstood what it meant. Would it be correct to say? The .NET event pattern has a signature of delegate void Handler(object sender, EventArgs args) if the event matched that use FromEventPattern (more verbose but, perhaps a littler clearer) – baralong Jun 27 '11 at 01:09
23

To elaborate on this a bit further, you can typically determine when to choose one of the FromEvent vs FromEventPattern by the type of event used in the class you're trying to observe. Use FromEventPattern when your event is of type EventHandler or the generic EventHandler<T>. Use FromEvent when you're using a custom, non-generic event handler type. The following examples are lifted directly from the Rx wiki, which has lots of good examples- 101 of them to be exact.

FromEventPattern (with generic EventHandler):

class ObserveEvent_Generic
{
    public class SomeEventArgs : EventArgs { }
    public static event EventHandler<SomeEventArgs> GenericEvent;

    static void Main()
    {
        // To consume GenericEvent as an IObservable:
        IObservable<EventPattern<SomeEventArgs>> eventAsObservable = Observable.FromEventPattern<SomeEventArgs>(
            ev => GenericEvent += ev,
            ev => GenericEvent -= ev );
    }
}

FromEvent:

class ObserveEvent_NonGeneric
{
    public class SomeEventArgs : EventArgs { }
    public delegate void SomeNonGenericEventHandler(object sender, SomeEventArgs e);
    public static event SomeNonGenericEventHandler NonGenericEvent;

    static void Main()
    {
        // To consume NonGenericEvent as an IObservable, first inspect the type of EventArgs used in the second parameter of the delegate.
        // In this case, it is SomeEventArgs.  Then, use as shown below.
        IObservable<IEvent<SomeEventArgs>> eventAsObservable = Observable.FromEvent(
            (EventHandler<SomeEventArgs> ev) => new SomeNonGenericEventHandler(ev), 
            ev => NonGenericEvent += ev,
            ev => NonGenericEvent -= ev);
    }
}
joelmdev
  • 11,083
  • 10
  • 65
  • 89
10

Apparently the new syntax has changed a bit. The current syntax is the following:

// get events as observable 
var events = Observable.FromEvent<MouseButtonEventHandler, MouseEventArgs>(
    handler => MouseUp += handler, handler => MouseUp -= handler);

// subscribe to events
var subscription = events.Subscribe(args => OnMouseUp()));

// always dispose subscriptions! 
subscription.Dispose(); 
MovGP0
  • 7,267
  • 3
  • 49
  • 42