using System;
using System.Reactive.Linq;

namespace RX_Sample._03_ReactiveX
{
    static class Extensions
    {
        public static IObservable<TField> FromPropertyAndEvent<T, TField, TArgs>(
            this T self, 
            Func<T, TField> valueFactory,
            Action<T, EventHandler<TArgs>> addHandler,
            Action<T, EventHandler<TArgs>> removeHandler)
        {
            return
                Observable
                .Start(() => valueFactory(self))
                .Merge(Observable
                    .FromEvent<EventHandler<TArgs>, TField>(
                        action => (sender, args) => action(valueFactory(self)),
                        handler => addHandler(self, handler),
                        handler => removeHandler(self, handler))
                    );
        }

        public static IObservable<TInner> Switch<TOuter, TInner>(this IObservable<TOuter> self, Func<TOuter, IObservable<TInner>> selector)
        {
            return self
                .Select(selector)
                .Switch();
        }
    }

    class EventSource
    {
        public int MyProperty { get; set; }
        public event EventHandler<int> SomeEvent;
    }
    class Sample04
    {
        public Sample04()
        {
            var eventSource = new EventSource();

            eventSource
                .FromPropertyAndEvent<EventSource, int, int>(
                    o => o.MyProperty,
                    (o, handler) => o.SomeEvent += handler,
                    (o, handler) => o.SomeEvent -= handler);
        }
    }
}
