// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System.Globalization; using System.Reactive.Concurrency; using System.Reactive.Disposables; using System.Reflection; using System.Threading; #if HAS_WINRT using System.Runtime.InteropServices.WindowsRuntime; #endif namespace System.Reactive.Linq { #if !NO_PERF using Observαble; #endif // // BREAKING CHANGE v2 > v1.x - FromEvent[Pattern] now has an implicit SubscribeOn and Publish operation. // // See FromEvent.cs for more information. // internal partial class QueryLanguage { #region + FromEventPattern + #region Strongly typed #region Action #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler) { return FromEventPattern_(addHandler, removeHandler, GetSchedulerForCurrentContext()); } public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler, IScheduler scheduler) { return FromEventPattern_(addHandler, removeHandler, scheduler); } #else public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler) { return FromEventPattern_(addHandler, removeHandler, GetSchedulerForCurrentContext()); } public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler, IScheduler scheduler) { return FromEventPattern_(addHandler, removeHandler, scheduler); } #endif #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(Action addHandler, Action removeHandler, IScheduler scheduler) { #if !NO_PERF return new FromEventPattern.τ(e => new EventHandler(e), addHandler, removeHandler, scheduler); #else var res = Observable.FromEventPattern(e => new EventHandler(e), addHandler, removeHandler); return SynchronizeEvents(res, scheduler); #endif } #else private static IObservable> FromEventPattern_(Action addHandler, Action removeHandler, IScheduler scheduler) { #if !NO_PERF return new FromEventPattern.τ(e => new EventHandler(e), addHandler, removeHandler, scheduler); #else var res = Observable.FromEventPattern(e => new EventHandler(e), addHandler, removeHandler); return SynchronizeEvents(res, scheduler); #endif } #endif #endregion #endregion #region Action #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler) #endif { return FromEventPattern_(addHandler, removeHandler, GetSchedulerForCurrentContext()); } #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler, IScheduler scheduler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler, IScheduler scheduler) #endif { return FromEventPattern_(addHandler, removeHandler, scheduler); } #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(Action addHandler, Action removeHandler, IScheduler scheduler) where TEventArgs : EventArgs #else private static IObservable> FromEventPattern_(Action addHandler, Action removeHandler, IScheduler scheduler) #endif { #if !NO_PERF return new FromEventPattern.τ(addHandler, removeHandler, scheduler); #else var res = new AnonymousObservable>(observer => { Action handler = (sender, eventArgs) => observer.OnNext(new EventPattern(sender, eventArgs)); var d = ReflectionUtils.CreateDelegate(handler, typeof(Action).GetMethod("Invoke")); addHandler(d); return Disposable.Create(() => removeHandler(d)); }); return SynchronizeEvents(res, scheduler); #endif } #endregion #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Func, TDelegate> conversion, Action addHandler, Action removeHandler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Func, TDelegate> conversion, Action addHandler, Action removeHandler) #endif { return FromEventPattern_(conversion, addHandler, removeHandler, GetSchedulerForCurrentContext()); } #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Func, TDelegate> conversion, Action addHandler, Action removeHandler, IScheduler scheduler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Func, TDelegate> conversion, Action addHandler, Action removeHandler, IScheduler scheduler) #endif { return FromEventPattern_(conversion, addHandler, removeHandler, scheduler); } #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(Func, TDelegate> conversion, Action addHandler, Action removeHandler, IScheduler scheduler) where TEventArgs : EventArgs #else private static IObservable> FromEventPattern_(Func, TDelegate> conversion, Action addHandler, Action removeHandler, IScheduler scheduler) #endif { #if !NO_PERF return new FromEventPattern.τ(conversion, addHandler, removeHandler, scheduler); #else var res = new AnonymousObservable>(observer => { var handler = conversion((sender, eventArgs) => observer.OnNext(new EventPattern(sender, eventArgs))); addHandler(handler); return Disposable.Create(() => removeHandler(handler)); }); return SynchronizeEvents(res, scheduler); #endif } #endregion #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler) #endif { return FromEventPattern_(addHandler, removeHandler, GetSchedulerForCurrentContext()); } #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler, IScheduler scheduler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Action addHandler, Action removeHandler, IScheduler scheduler) #endif { return FromEventPattern_(addHandler, removeHandler, scheduler); } #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(Action addHandler, Action removeHandler, IScheduler scheduler) where TEventArgs : EventArgs #else private static IObservable> FromEventPattern_(Action addHandler, Action removeHandler, IScheduler scheduler) #endif { #if !NO_PERF return new FromEventPattern.τ(addHandler, removeHandler, scheduler); #else var res = new AnonymousObservable>(observer => { Action handler = (sender, eventArgs) => observer.OnNext(new EventPattern(sender, eventArgs)); var d = ReflectionUtils.CreateDelegate(handler, typeof(Action).GetMethod("Invoke")); addHandler(d); return Disposable.Create(() => removeHandler(d)); }); return SynchronizeEvents(res, scheduler); #endif } #endregion #endregion #region Action> #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Action> addHandler, Action> removeHandler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Action> addHandler, Action> removeHandler) #endif { return FromEventPattern_(addHandler, removeHandler, GetSchedulerForCurrentContext()); } #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Action> addHandler, Action> removeHandler, IScheduler scheduler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Action> addHandler, Action> removeHandler, IScheduler scheduler) #endif { return FromEventPattern_(addHandler, removeHandler, scheduler); } #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(Action> addHandler, Action> removeHandler, IScheduler scheduler) where TEventArgs : EventArgs #else private static IObservable> FromEventPattern_(Action> addHandler, Action> removeHandler, IScheduler scheduler) #endif { #if !NO_PERF return new FromEventPattern.τ, TEventArgs>(handler => handler, addHandler, removeHandler, scheduler); #else var res = Observable.FromEventPattern, TEventArgs>(handler => handler, addHandler, removeHandler); return SynchronizeEvents(res, scheduler); #endif } #endregion #endregion #endregion #region Reflection #region Instance events #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(object target, string eventName) { return FromEventPattern_(target, eventName, GetSchedulerForCurrentContext()); } public virtual IObservable> FromEventPattern(object target, string eventName, IScheduler scheduler) { return FromEventPattern_(target, eventName, scheduler); } #else public virtual IObservable> FromEventPattern(object target, string eventName) { return FromEventPattern_(target, eventName, GetSchedulerForCurrentContext()); } public virtual IObservable> FromEventPattern(object target, string eventName, IScheduler scheduler) { return FromEventPattern_(target, eventName, scheduler); } #endif #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(object target, string eventName, IScheduler scheduler) { return FromEventPattern_>(target.GetType(), target, eventName, (sender, args) => new EventPattern(sender, args), scheduler); } #else private static IObservable> FromEventPattern_(object target, string eventName, IScheduler scheduler) { return FromEventPattern_>(target.GetType(), target, eventName, (sender, args) => new EventPattern(sender, args), scheduler); } #endif #endregion #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(object target, string eventName) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(object target, string eventName) #endif { return FromEventPattern_(target, eventName, GetSchedulerForCurrentContext()); } #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(object target, string eventName, IScheduler scheduler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(object target, string eventName, IScheduler scheduler) #endif { return FromEventPattern_(target, eventName, scheduler); } #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(object target, string eventName, IScheduler scheduler) where TEventArgs : EventArgs #else private static IObservable> FromEventPattern_(object target, string eventName, IScheduler scheduler) #endif { return FromEventPattern_>(target.GetType(), target, eventName, (sender, args) => new EventPattern(sender, args), scheduler); } #endregion #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(object target, string eventName) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(object target, string eventName) #endif { return FromEventPattern_(target, eventName, GetSchedulerForCurrentContext()); } #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(object target, string eventName, IScheduler scheduler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(object target, string eventName, IScheduler scheduler) #endif { return FromEventPattern_(target, eventName, scheduler); } #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(object target, string eventName, IScheduler scheduler) where TEventArgs : EventArgs #else private static IObservable> FromEventPattern_(object target, string eventName, IScheduler scheduler) #endif { return FromEventPattern_>(target.GetType(), target, eventName, (sender, args) => new EventPattern(sender, args), scheduler); } #endregion #endregion #region Static events #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Type type, string eventName) { return FromEventPattern_(type, eventName, GetSchedulerForCurrentContext()); } public virtual IObservable> FromEventPattern(Type type, string eventName, IScheduler scheduler) { return FromEventPattern_(type, eventName, scheduler); } #else public virtual IObservable> FromEventPattern(Type type, string eventName) { return FromEventPattern_(type, eventName, GetSchedulerForCurrentContext()); } public virtual IObservable> FromEventPattern(Type type, string eventName, IScheduler scheduler) { return FromEventPattern_(type, eventName, scheduler); } #endif #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(Type type, string eventName, IScheduler scheduler) { return FromEventPattern_>(type, null, eventName, (sender, args) => new EventPattern(sender, args), scheduler); } #else private static IObservable> FromEventPattern_(Type type, string eventName, IScheduler scheduler) { return FromEventPattern_>(type, null, eventName, (sender, args) => new EventPattern(sender, args), scheduler); } #endif #endregion #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Type type, string eventName) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Type type, string eventName) #endif { return FromEventPattern_(type, eventName, GetSchedulerForCurrentContext()); } #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Type type, string eventName, IScheduler scheduler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Type type, string eventName, IScheduler scheduler) #endif { return FromEventPattern_(type, eventName, scheduler); } #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(Type type, string eventName, IScheduler scheduler) where TEventArgs : EventArgs #else private static IObservable> FromEventPattern_(Type type, string eventName, IScheduler scheduler) #endif { return FromEventPattern_>(type, null, eventName, (sender, args) => new EventPattern(sender, args), scheduler); } #endregion #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Type type, string eventName) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Type type, string eventName) #endif { return FromEventPattern_(type, eventName, GetSchedulerForCurrentContext()); } #if !NO_EVENTARGS_CONSTRAINT public virtual IObservable> FromEventPattern(Type type, string eventName, IScheduler scheduler) where TEventArgs : EventArgs #else public virtual IObservable> FromEventPattern(Type type, string eventName, IScheduler scheduler) #endif { return FromEventPattern_(type, eventName, scheduler); } #region Implementation #if !NO_EVENTARGS_CONSTRAINT private static IObservable> FromEventPattern_(Type type, string eventName, IScheduler scheduler) where TEventArgs : EventArgs #else private static IObservable> FromEventPattern_(Type type, string eventName, IScheduler scheduler) #endif { return FromEventPattern_>(type, null, eventName, (sender, args) => new EventPattern(sender, args), scheduler); } #endregion #endregion #region Helper methods private static IObservable FromEventPattern_(Type targetType, object target, string eventName, Func getResult, IScheduler scheduler) #if !NO_EVENTARGS_CONSTRAINT where TEventArgs : EventArgs #endif { var addMethod = default(MethodInfo); var removeMethod = default(MethodInfo); var delegateType = default(Type); var isWinRT = default(bool); ReflectionUtils.GetEventMethods(targetType, target, eventName, out addMethod, out removeMethod, out delegateType, out isWinRT); #if HAS_WINRT if (isWinRT) { #if !NO_PERF return new FromEventPattern.ρ(target, delegateType, addMethod, removeMethod, getResult, true, scheduler); #else return new AnonymousObservable(observer => { Action handler = (sender, eventArgs) => observer.OnNext(getResult(sender, eventArgs)); var d = ReflectionUtils.CreateDelegate(delegateType, handler, typeof(Action).GetMethod("Invoke")); var token = addMethod.Invoke(target, new object[] { d }); return Disposable.Create(() => removeMethod.Invoke(target, new object[] { token })); }); #endif } #endif #if !NO_PERF return new FromEventPattern.ρ(target, delegateType, addMethod, removeMethod, getResult, false, scheduler); #else var res = new AnonymousObservable(observer => { Action handler = (sender, eventArgs) => observer.OnNext(getResult(sender, eventArgs)); var d = ReflectionUtils.CreateDelegate(delegateType, handler, typeof(Action).GetMethod("Invoke")); addMethod.Invoke(target, new object[] { d }); return Disposable.Create(() => removeMethod.Invoke(target, new object[] { d })); }); return SynchronizeEvents(res, scheduler); #endif } #endregion #endregion #endregion #region FromEvent public virtual IObservable FromEvent(Func, TDelegate> conversion, Action addHandler, Action removeHandler) { return FromEvent_(conversion, addHandler, removeHandler, GetSchedulerForCurrentContext()); } public virtual IObservable FromEvent(Func, TDelegate> conversion, Action addHandler, Action removeHandler, IScheduler scheduler) { return FromEvent_(conversion, addHandler, removeHandler, scheduler); } #region Implementation private static IObservable FromEvent_(Func, TDelegate> conversion, Action addHandler, Action removeHandler, IScheduler scheduler) { #if !NO_PERF return new FromEvent(conversion, addHandler, removeHandler, scheduler); #else var res = new AnonymousObservable(observer => { var handler = conversion(observer.OnNext); addHandler(handler); return Disposable.Create(() => removeHandler(handler)); }); return SynchronizeEvents(res, scheduler); #endif } #endregion public virtual IObservable FromEvent(Action addHandler, Action removeHandler) { return FromEvent_(addHandler, removeHandler, GetSchedulerForCurrentContext()); } public virtual IObservable FromEvent(Action addHandler, Action removeHandler, IScheduler scheduler) { return FromEvent_(addHandler, removeHandler, scheduler); } #region Implementation private static IObservable FromEvent_(Action addHandler, Action removeHandler, IScheduler scheduler) { #if !NO_PERF return new FromEvent(addHandler, removeHandler, scheduler); #else var res = new AnonymousObservable(observer => { Action handler = observer.OnNext; var d = ReflectionUtils.CreateDelegate(handler, typeof(Action).GetMethod("Invoke")); addHandler(d); return Disposable.Create(() => removeHandler(d)); }); return SynchronizeEvents(res, scheduler); #endif } #endregion public virtual IObservable FromEvent(Action> addHandler, Action> removeHandler) { return FromEvent_(addHandler, removeHandler, GetSchedulerForCurrentContext()); } public virtual IObservable FromEvent(Action> addHandler, Action> removeHandler, IScheduler scheduler) { return FromEvent_(addHandler, removeHandler, scheduler); } #region Implementation private static IObservable FromEvent_(Action> addHandler, Action> removeHandler, IScheduler scheduler) { #if !NO_PERF return new FromEvent, TEventArgs>(h => h, addHandler, removeHandler, scheduler); #else var res = Observable.FromEvent, TEventArgs>(h => h, addHandler, removeHandler); return SynchronizeEvents(res, scheduler); #endif } #endregion public virtual IObservable FromEvent(Action addHandler, Action removeHandler) { return FromEvent_(addHandler, removeHandler, GetSchedulerForCurrentContext()); } public virtual IObservable FromEvent(Action addHandler, Action removeHandler, IScheduler scheduler) { return FromEvent_(addHandler, removeHandler, scheduler); } #region Implementation private static IObservable FromEvent_(Action addHandler, Action removeHandler, IScheduler scheduler) { #if !NO_PERF return new FromEvent(h => new Action(() => h(new Unit())), addHandler, removeHandler, scheduler); #else var res = Observable.FromEvent(h => new Action(() => h(new Unit())), addHandler, removeHandler); return SynchronizeEvents(res, scheduler); #endif } #endregion #endregion #region Helpers private static IScheduler GetSchedulerForCurrentContext() { var context = SynchronizationContext.Current; if (context != null) return new SynchronizationContextScheduler(context, false); else return SchedulerDefaults.ConstantTimeOperations; } #if NO_PERF private static IObservable SynchronizeEvents(IObservable source, IScheduler scheduler) { return source.SubscribeOn(scheduler).Publish().RefCount(); } #endif #endregion } }