Ejemplo n.º 1
0
        public void BindToIsNotFooledByIntermediateObjectSwitching()
        {
            new TestScheduler().With(sched =>
            {
                var input   = new ScheduledSubject <string>(sched);
                var fixture = new HostTestFixture {
                    Child = new TestFixture()
                };

                input.BindTo(fixture, x => x.Child.IsNotNullString);

                Assert.Null(fixture.Child.IsNotNullString);

                input.OnNext("Foo");
                sched.Start();
                Assert.Equal("Foo", fixture.Child.IsNotNullString);

                fixture.Child = new TestFixture();
                sched.Start();
                Assert.Equal("Foo", fixture.Child.IsNotNullString);

                input.OnNext("Bar");
                sched.Start();
                Assert.Equal("Bar", fixture.Child.IsNotNullString);
            });
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates a new ReactiveCommand object.
        /// </summary>
        /// <param name="canExecute">An Observable, often obtained via
        /// ObservableFromProperty, that defines when the Command can
        /// execute.</param>
        /// <param name="scheduler">The scheduler to publish events on - default
        /// is RxApp.DeferredScheduler.</param>
        public ReactiveCommand(IObservable <bool> canExecute = null, IScheduler scheduler = null)
        {
            scheduler = scheduler ?? RxApp.DeferredScheduler;

            var ceSubj = (canExecute ?? Observable.Return(true))
                         .Multicast(new ScheduledSubject <bool>(scheduler));

            CanExecuteObservable = ceSubj.DistinctUntilChanged();
            ceSubj.Subscribe(
                x => {
                if (x == _latestCanExecute)
                {
                    return;
                }
                _latestCanExecute = x;
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, new EventArgs());
                }
            },
                ex => { this.Log().Warn("CanExecute threw", ex); _latestCanExecute = false; });

            _executeSubject = new ScheduledSubject <object>(scheduler);

            _inner = ceSubj.Connect();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a new ReactiveCommand object.
        /// </summary>
        /// <param name="canExecute">An Observable, often obtained via
        /// ObservableFromProperty, that defines when the Command can
        /// execute.</param>
        /// <param name="scheduler">The scheduler to publish events on - default
        /// is RxApp.DeferredScheduler.</param>
        public ReactiveCommand(IObservable <bool> canExecute = null, IScheduler scheduler = null)
        {
            canExecute = canExecute ?? Observable.Return(true).Concat(Observable.Never <bool>());
            commonCtor(scheduler);

            var exSubject = new ScheduledSubject <Exception>(RxApp.DeferredScheduler, RxApp.DefaultExceptionHandler);

            _inner = canExecute.Subscribe(
                canExecuteSubject.OnNext,
                exSubject.OnNext);

            ThrownExceptions = exSubject;
        }
Ejemplo n.º 4
0
        protected ReactiveCommand(Func <object, Task <bool> > canExecuteFunc, IScheduler scheduler = null)
        {
            var canExecute = canExecuteProbed.SelectMany(x => canExecuteFunc(x).ToObservable());

            commonCtor(scheduler);

            var exSubject = new ScheduledSubject <Exception>(RxApp.DeferredScheduler, RxApp.DefaultExceptionHandler);

            _inner = canExecute.Subscribe(
                canExecuteSubject.OnNext,
                exSubject.OnNext);

            ThrownExceptions = exSubject;
        }
Ejemplo n.º 5
0
        void commonCtor(IScheduler scheduler)
        {
            this.scheduler = scheduler ?? RxApp.DeferredScheduler;

            canExecuteSubject = new ScheduledSubject <bool>(RxApp.DeferredScheduler);
            canExecuteLatest  = new ObservableAsPropertyHelper <bool>(canExecuteSubject,
                                                                      b => { if (CanExecuteChanged != null)
                                                                             {
                                                                                 CanExecuteChanged(this, EventArgs.Empty);
                                                                             }
                                                                      },
                                                                      true, scheduler);

            executeSubject = new Subject <object>();
        }
Ejemplo n.º 6
0
        void commonCtor(IScheduler scheduler, bool initialCondition = true)
        {
            this.scheduler = scheduler ?? RxApp.MainThreadScheduler;

            _canExecuteSubject = new ScheduledSubject <bool>(RxApp.MainThreadScheduler);
            canExecuteLatest   = new ObservableAsPropertyHelper <bool>(_canExecuteSubject,
                                                                       b => { this.raiseCanExecuteChanged(EventArgs.Empty); },
                                                                       initialCondition, scheduler);

            _canExecuteProbed = new Subject <object>();
            executeSubject    = new Subject <object>();

            _exSubject       = new ScheduledSubject <Exception>(RxApp.MainThreadScheduler, RxApp.DefaultExceptionHandler);
            ThrownExceptions = _exSubject;
        }
Ejemplo n.º 7
0
        public InstallingViewModel(IScreen hostScreen)
        {
            HostScreen = hostScreen;

            var progress = new ScheduledSubject<int>(RxApp.DeferredScheduler);
            ProgressValue = progress;

            progress.ToProperty(this, x => x.LatestProgress, 0);

            this.WhenAny(x => x.PackageMetadata, x => x.Value.ExtractTitle())
                .ToProperty(this, x => x.Title);

            this.WhenAny(x => x.PackageMetadata, v => v.Value)
                .Select(x => x != null ? x.Description : String.Empty)
                .ToProperty(this, x => x.Description);
        }
Ejemplo n.º 8
0
        void commonCtor(int maximumConcurrent, IScheduler scheduler, IObservable <bool> canExecute = null, bool initialCondition = true)
        {
            _normalSched       = scheduler ?? RxApp.DeferredScheduler;
            _canExecuteSubject = new ScheduledSubject <bool>(_normalSched);
            _executeSubject    = new ScheduledSubject <object>(Scheduler.Immediate);
            _exSubject         = new ScheduledSubject <Exception>(_normalSched, RxApp.DefaultExceptionHandler);

            AsyncStartedNotification   = new ScheduledSubject <Unit>(RxApp.DeferredScheduler);
            AsyncCompletedNotification = new ScheduledSubject <Unit>(RxApp.DeferredScheduler);

            ItemsInflight = Observable.Merge(
                AsyncStartedNotification.Select(_ => 1),
                AsyncCompletedNotification.Select(_ => - 1)
                ).Scan(0, (acc, x) => {
                var ret = acc + x;
                if (ret < 0)
                {
                    this.Log().Fatal("Reference count dropped below zero");
                }
                return(ret);
            }).Multicast(new BehaviorSubject <int>(0)).PermaRef().ObserveOn(RxApp.DeferredScheduler);

            bool startCE = (_canExecuteExplicitFunc != null ? _canExecuteExplicitFunc(null) : initialCondition);

            CanExecuteObservable = Observable.CombineLatest(
                _canExecuteSubject.StartWith(startCE), ItemsInflight.Select(x => x < maximumConcurrent).StartWith(true),
                (canEx, slotsAvail) => canEx && slotsAvail)
                                   .DistinctUntilChanged();

            CanExecuteObservable.Subscribe(x => {
                this.Log().Debug("Setting canExecuteLatest to {0}", x);
                _canExecuteLatest = x;
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, new EventArgs());
                }
            });

            if (canExecute != null)
            {
                _inner = canExecute.Subscribe(_canExecuteSubject.OnNext, _exSubject.OnNext);
            }

            MaximumConcurrent = maximumConcurrent;

            ThrownExceptions = _exSubject;
        }
Ejemplo n.º 9
0
        public InstallingViewModel(IScreen hostScreen)
        {
            HostScreen = hostScreen;

            var progress = new ScheduledSubject <int>(RxApp.DeferredScheduler);

            ProgressValue = progress;

            progress.ToProperty(this, x => x.LatestProgress, 0);

            this.WhenAny(x => x.PackageMetadata, x => x.Value.ExtractTitle())
            .ToProperty(this, x => x.Title);

            this.WhenAny(x => x.PackageMetadata, v => v.Value)
            .Select(x => x != null ? x.Description : String.Empty)
            .ToProperty(this, x => x.Description);
        }
Ejemplo n.º 10
0
        public UninstallingViewModel(IScreen hostScreen)
        {
            HostScreen = hostScreen;

            var progress = new ScheduledSubject<int>(RxApp.DeferredScheduler);
            ProgressValue = progress;

            progress.ToProperty(this, x => x.LatestProgress, 0);

            this.WhenAny(x => x.PackageMetadata, x => x.Value)
                .SelectMany(x => x != null ? Observable.Return(x.Title) : Observable.Empty<string>())
                .ToProperty(this, x => x.Title);

            this.WhenAny(x => x.PackageMetadata, x => x.Value)
                .SelectMany(x => x != null ? Observable.Return(x.Description) : Observable.Empty<string>())
                .ToProperty(this, x => x.Description);
        }
Ejemplo n.º 11
0
        public UninstallingViewModel(IScreen hostScreen)
        {
            HostScreen = hostScreen;

            var progress = new ScheduledSubject <int>(RxApp.DeferredScheduler);

            ProgressValue = progress;

            progress.ToProperty(this, x => x.LatestProgress, 0);

            this.WhenAny(x => x.PackageMetadata, x => x.Value)
            .SelectMany(x => x != null ? Observable.Return(x.Title) : Observable.Empty <string>())
            .ToProperty(this, x => x.Title);

            this.WhenAny(x => x.PackageMetadata, x => x.Value)
            .SelectMany(x => x != null ? Observable.Return(x.Description) : Observable.Empty <string>())
            .ToProperty(this, x => x.Description);
        }
Ejemplo n.º 12
0
        private ISubject <T> setupSubjectIfNecessary <T>(string contract)
        {
            ISubject <T> ret = null;

            withMessageBus(typeof(T), contract, (mb, tuple) =>
            {
                if (mb.TryGetValue(tuple, out var subjRef) && subjRef.IsAlive)
                {
                    ret = (ISubject <T>)subjRef.Target;
                    return;
                }

                ret       = new ScheduledSubject <T>(getScheduler(tuple), null, new BehaviorSubject <T>(default(T)));
                mb[tuple] = new NotAWeakReference(ret);
            });

            return(ret);
        }
        public void BindToSmokeTest()
        {
            (new TestScheduler()).With(sched => {
                var input = new ScheduledSubject<string>(sched);
                var fixture = new HostTestFixture() {Child = new TestFixture()};

                input.BindTo(fixture, x => x.Child.IsNotNullString);

                Assert.Null(fixture.Child.IsNotNullString);

                input.OnNext("Foo");
                sched.Start();
                Assert.Equal("Foo", fixture.Child.IsNotNullString);

                input.OnNext("Bar");
                sched.Start();
                Assert.Equal("Bar", fixture.Child.IsNotNullString);
            });
        }
Ejemplo n.º 14
0
        public ReactiveCommand(IObservable <bool> canExecute, bool allowsConcurrentExecution, IScheduler scheduler, bool initialCondition = true)
        {
            canExecute                = canExecute ?? Observable.Return(true);
            defaultScheduler          = scheduler ?? RxApp.MainThreadScheduler;
            AllowsConcurrentExecution = allowsConcurrentExecution;

            canExecute = canExecute.Catch <bool, Exception>(ex => {
                exceptions.OnNext(ex);
                return(Observable.Empty <bool>());
            });

            ThrownExceptions = exceptions = new ScheduledSubject <Exception>(defaultScheduler, RxApp.DefaultExceptionHandler);

            var isExecuting = inflight
                              .Scan(0, (acc, x) => acc + (x ? 1 : -1))
                              .Select(x => x > 0)
                              .Publish(false)
                              .PermaRef()
                              .DistinctUntilChanged();

            IsExecuting = isExecuting.ObserveOn(defaultScheduler);

            var isBusy = allowsConcurrentExecution ? Observable.Return(false) : isExecuting;
            var canExecuteAndNotBusy = Observable.CombineLatest(canExecute, isBusy, (ce, b) => ce && !b);

            var canExecuteObs = canExecuteAndNotBusy
                                .Publish(initialCondition)
                                .RefCount();

            CanExecuteObservable = canExecuteObs
                                   .DistinctUntilChanged()
                                   .ObserveOn(defaultScheduler);

            innerDisp = canExecuteObs.Subscribe(x => {
                if (canExecuteLatest == x)
                {
                    return;
                }

                canExecuteLatest = x;
                defaultScheduler.Schedule(() => this.raiseCanExecuteChanged(EventArgs.Empty));
            }, exceptions.OnNext);
        }
        public void DisposingDisconnectsTheBindTo()
        {
            (new TestScheduler()).With(sched => {
                var input = new ScheduledSubject<string>(sched);
                var fixture = new HostTestFixture() {Child = new TestFixture()};

                var subscription = input.BindTo(fixture, x => x.Child.IsNotNullString);

                Assert.Null(fixture.Child.IsNotNullString);

                input.OnNext("Foo");
                sched.Start();
                Assert.Equal("Foo", fixture.Child.IsNotNullString);

                subscription.Dispose();

                input.OnNext("Bar");
                sched.Start();
                Assert.Equal("Foo", fixture.Child.IsNotNullString);
            });
        }
        public void BindToSmokeTest()
        {
            (new TestScheduler()).With(sched => {
                var input   = new ScheduledSubject <string>(sched);
                var fixture = new HostTestFixture()
                {
                    Child = new TestFixture()
                };

                input.BindTo(fixture, x => x.Child.IsNotNullString);

                Assert.Null(fixture.Child.IsNotNullString);

                input.OnNext("Foo");
                sched.Start();
                Assert.Equal("Foo", fixture.Child.IsNotNullString);

                input.OnNext("Bar");
                sched.Start();
                Assert.Equal("Bar", fixture.Child.IsNotNullString);
            });
        }
        public void BindToIsNotFooledByIntermediateObjectSwitching()
        {
            (new TestScheduler()).With(sched => {
                var input = new ScheduledSubject<string>(sched);
                var fixture = new HostTestFixture() {Child = new TestFixture()};

                var subscription = input.BindTo(fixture, x => x.Child.IsNotNullString);

                Assert.Null(fixture.Child.IsNotNullString);

                input.OnNext("Foo");
                sched.Start();
                Assert.Equal("Foo", fixture.Child.IsNotNullString);

                fixture.Child = new TestFixture();
                sched.Start();
                Assert.Null(fixture.Child.IsNotNullString);

                input.OnNext("Bar");
                sched.Start();
                Assert.Equal("Bar", fixture.Child.IsNotNullString);
            });
        }
Ejemplo n.º 18
0
        public void DisposingDisconnectsTheBindTo()
        {
            new TestScheduler().With(sched =>
            {
                var input   = new ScheduledSubject <string>(sched);
                var fixture = new HostTestFixture {
                    Child = new TestFixture()
                };

                var subscription = input.BindTo(fixture, x => x.Child.IsNotNullString);

                Assert.Null(fixture.Child.IsNotNullString);

                input.OnNext("Foo");
                sched.Start();
                Assert.Equal("Foo", fixture.Child.IsNotNullString);

                subscription.Dispose();

                input.OnNext("Bar");
                sched.Start();
                Assert.Equal("Foo", fixture.Child.IsNotNullString);
            });
        }
Ejemplo n.º 19
0
 public ReactiveViewModel()
 {
     _thrownExceptions = new ScheduledSubject <Exception>(CurrentThreadScheduler.Instance, _defaultExceptionHandler);
 }
    /// <summary>
    /// Initializes a new instance of the <see cref="CombinedReactiveCommand{TParam, TResult}"/> class.
    /// </summary>
    /// <param name="childCommands">The child commands which will be executed.</param>
    /// <param name="canExecute">A observable when the command can be executed.</param>
    /// <param name="outputScheduler">The scheduler where to dispatch the output from the command.</param>
    /// <param name="canExecuteScheduler">
    /// An optional scheduler that is used for CanExecute and IsExecuting events. Defaults to <c>RxApp.MainThreadScheduler</c>.
    /// </param>
    /// <exception cref="ArgumentNullException">Fires when required arguments are null.</exception>
    /// <exception cref="ArgumentException">Fires if the child commands container is empty.</exception>
    protected internal CombinedReactiveCommand(
        IEnumerable <ReactiveCommandBase <TParam, TResult> > childCommands,
        IObservable <bool> canExecute,
        IScheduler outputScheduler,
        IScheduler canExecuteScheduler)
    {
        if (childCommands is null)
        {
            throw new ArgumentNullException(nameof(childCommands));
        }

        if (canExecute is null)
        {
            throw new ArgumentNullException(nameof(canExecute));
        }

        if (outputScheduler is null)
        {
            throw new ArgumentNullException(nameof(outputScheduler));
        }

        if (canExecuteScheduler is null)
        {
            throw new ArgumentNullException(nameof(canExecuteScheduler));
        }

        var childCommandsArray = childCommands.ToArray();

        if (childCommandsArray.Length == 0)
        {
            throw new ArgumentException("No child commands provided.", nameof(childCommands));
        }

        _exceptions = new ScheduledSubject <Exception>(outputScheduler, RxApp.DefaultExceptionHandler);

        var canChildrenExecute = childCommandsArray.Select(x => x.CanExecute)
                                 .CombineLatest()
                                 .Select(x => x.All(y => y));
        var combinedCanExecute = canExecute
                                 .Catch <bool, Exception>(ex =>
        {
            _exceptions.OnNext(ex);
            return(Observables.False);
        })
                                 .StartWith(false)
                                 .CombineLatest(canChildrenExecute, (ce, cce) => ce && cce)
                                 .DistinctUntilChanged()
                                 .Replay(1)
                                 .RefCount()
                                 .ObserveOn(canExecuteScheduler);

        _exceptionsSubscription = childCommandsArray.Select(x => x.ThrownExceptions)
                                  .Merge()
                                  .Subscribe(ex => _exceptions.OnNext(ex));

        _innerCommand = new ReactiveCommand <TParam, IList <TResult> >(
            param =>
            childCommandsArray
            .Select(x => x.Execute(param))
            .CombineLatest(),
            combinedCanExecute,
            outputScheduler,
            canExecuteScheduler);

        // we already handle exceptions on individual child commands above, but the same exception
        // will tick through innerCommand. Therefore, we need to ensure we ignore it or the default
        // handler will execute and the process will be torn down
        _innerCommand
        .ThrownExceptions
        .Subscribe();

        CanExecute.Subscribe(OnCanExecuteChanged);
    }