// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. #if !NO_PERF using System; using System.Reactive.Concurrency; using System.Reactive.Disposables; using System.Reflection; using System.Threading; // // BREAKING CHANGE v2 > v1.x - FromEvent[Pattern] now has an implicit SubscribeOn and Publish operation. // // See FromEvent.cs for more information. // namespace System.Reactive.Linq.ObservableImpl { class FromEventPattern { public class Impl : ClassicEventProducer> { private readonly Func, TDelegate> _conversion; public Impl(Action addHandler, Action removeHandler, IScheduler scheduler) : base(addHandler, removeHandler, scheduler) { } public Impl(Func, TDelegate> conversion, Action addHandler, Action removeHandler, IScheduler scheduler) : base(addHandler, removeHandler, scheduler) { _conversion = conversion; } protected override TDelegate GetHandler(Action> onNext) { var handler = default(TDelegate); if (_conversion == null) { Action h = (sender, eventArgs) => onNext(new EventPattern(sender, eventArgs)); handler = ReflectionUtils.CreateDelegate(h, typeof(Action).GetMethod(nameof(Action.Invoke))); } else { handler = _conversion((sender, eventArgs) => onNext(new EventPattern(sender, eventArgs))); } return handler; } } public class Impl : ClassicEventProducer> { public Impl(Action addHandler, Action removeHandler, IScheduler scheduler) : base(addHandler, removeHandler, scheduler) { } protected override TDelegate GetHandler(Action> onNext) { Action h = (sender, eventArgs) => onNext(new EventPattern(sender, eventArgs)); return ReflectionUtils.CreateDelegate(h, typeof(Action).GetMethod(nameof(Action.Invoke))); } } public class Handler : EventProducer { private readonly object _target; private readonly Type _delegateType; private readonly MethodInfo _addMethod; private readonly MethodInfo _removeMethod; private readonly Func _getResult; #if HAS_WINRT private readonly bool _isWinRT; #endif public Handler(object target, Type delegateType, MethodInfo addMethod, MethodInfo removeMethod, Func getResult, bool isWinRT, IScheduler scheduler) : base(scheduler) { #if HAS_WINRT _isWinRT = isWinRT; #else System.Diagnostics.Debug.Assert(!isWinRT); #endif _target = target; _delegateType = delegateType; _addMethod = addMethod; _removeMethod = removeMethod; _getResult = getResult; } protected override Delegate GetHandler(Action onNext) { Action h = (sender, eventArgs) => onNext(_getResult(sender, eventArgs)); return ReflectionUtils.CreateDelegate(_delegateType, h, typeof(Action).GetMethod(nameof(Action.Invoke))); } protected override IDisposable AddHandler(Delegate handler) { var removeHandler = default(Action); try { #if HAS_WINRT if (_isWinRT) { var token = _addMethod.Invoke(_target, new object[] { handler }); removeHandler = () => _removeMethod.Invoke(_target, new object[] { token }); } else #endif { _addMethod.Invoke(_target, new object[] { handler }); removeHandler = () => _removeMethod.Invoke(_target, new object[] { handler }); } } catch (TargetInvocationException tie) { throw tie.InnerException; } return Disposable.Create(() => { try { removeHandler(); } catch (TargetInvocationException tie) { throw tie.InnerException; } }); } } } } #endif