2

There appears to be no overload of the FromEvent or FromEventPattern methods that will convert into an IObservable<T> an event with the type TDelegate only where there is more than one parameter and there is no EventArgs.

For e.g. it appears that we cannot convert the following into observables.

public event Action<int, int> SomethingHappened;

public event Func<string, int> SomethingElseHappened;

We either have to have an EventArgs in there somewhere or have a TDelegate with just a single parameter in its signature. So, the following are convertible because they have an EventArgs in their implicit delegate.

public event NameChangedHandler NameChanged;
public event EventHandler RollNumberChanged;
public event EventHandler<AgeChangedEventArgs> AgeChanged;


public delegate void NameChangedHandler(
                     object sender, 
                     NameChangedEventArgs e);

And this one also can be converted because it has a single T in its parameter.

public event Action<Tuple<string, string>> ClassChanged;

What do I do if I have an event like so:

public event Action<T1, T2...> ItHappened;
Water Cooler v2
  • 32,724
  • 54
  • 166
  • 336

2 Answers2

4

Using class Tester

public class Tester
{
    public void FireEvent(int i1, int i2, int i3)
    {
        if(ItHappened != null)
            ItHappened(i1, i2, i3);
    }

    public event Action<int, int, int> ItHappened;
}

You can use this signature Observable.FromEvent<TDelegate, TEventArgs> (Func<Action<TEventArgs>, TDelegate>, Action<TDelegate>, Action<TDelegate>) with the conversion function like so:

var t3 = new Tester();
IObservable<Tuple<int, int, int>> observable = Observable.FromEvent<Action<int, int, int>, Tuple<int, int, int>>(
    onNextHandler => (int i1, int i2, int i3) => onNextHandler(Tuple.Create(i1, i2, i3)),
    h => t3.ItHappened += h,
    h => t3.ItHappened -= h);

using (var disposable = observable.Subscribe(t => Console.WriteLine($"{{{t.Item1}, {t.Item2}, {t.Item3}}}")))
{
    t3.FireEvent(1, 2, 3);
}
t3.FireEvent(1, 2, 3);

There's a great reference on that overload here.

Community
  • 1
  • 1
Shlomo
  • 14,102
  • 3
  • 28
  • 43
  • Very many thanks and sorry for the late response. I'd not had a chance to touch Rx since. I will be resuming my study of it soon again. – Water Cooler v2 Sep 18 '16 at 04:18
  • I was aware of the overload and had used it in the past for conversions. Probably wasn't applying my mind enough to see that it would work in this case, too. – Water Cooler v2 Sep 18 '16 at 04:21
2

I must say I struggled with the event public event Func<string, int> SomethingElseHappened;, but this is a weird one where the event actually returns a value.

With public event Action<int, int> SomethingHappened;, however, it's quite easy with FromEvent.

Given this class:

public class Foo
{
    public event Action<int, int> SomethingHappened;

    public void OnSomethingHappened(int x, int y)
    {
        this.SomethingHappened?.Invoke(x, y);
    }
}

...then this code:

var foo = new Foo();

var fooSomethingHappened =
    Observable
        .FromEvent<Action<int, int>, Tuple<int, int>>(
            a => (x, y) => a(Tuple.Create(x, y)),
            h => foo.SomethingHappened += h,
            h => foo.SomethingHappened -= h);

fooSomethingHappened
    .Subscribe(t =>
        Console.WriteLine("SomethingHappened: {0} & {1}", t.Item1, t.Item2));

foo.OnSomethingHappened(3, 5);

...gives us:

SomethingHappened: 3 & 5
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • Thank you, thank you and sorry about the late response. – Water Cooler v2 Sep 18 '16 at 04:19
  • Sorry, both the answers are just fabulous. I didn't know which one to choose as the right one, so chose purely randomly because the other one also has a link. I love your answer, though. – Water Cooler v2 Sep 18 '16 at 04:22
  • @Enigmativity A long time ago so a long shot for an update now, but did anyone ever get this working with an event with the signature `public event Func SomeEvent;` e.g the signalR hubconnection closed event is: `public event Func Closed;` – Adam Diament Sep 24 '20 at 05:56
  • 1
    @AdamDiament - I'l away at the moment. Ping me in a week and I'll look at it. – Enigmativity Sep 27 '20 at 02:40