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); }); }
/// <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(); }
/// <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; }
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; }
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>(); }
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; }
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); }
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; }
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); }
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); }
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); }
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); }); }
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); }); }
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 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); }