public SpotTilePricingViewModel(ICurrencyPair currencyPair, SpotTileSubscriptionMode spotTileSubscriptionMode, ISpotTileViewModel parent, Func<Direction, ISpotTilePricingViewModel, IOneWayPriceViewModel> oneWayPriceFactory, IReactiveTrader reactiveTrader, IConcurrencyService concurrencyService, IConstantRatePump constantRatePump, ILoggerFactory loggerFactory) { _currencyPair = currencyPair; _subscriptionMode = spotTileSubscriptionMode; _parent = parent; _priceLatencyRecorder = reactiveTrader.PriceLatencyRecorder; _concurrencyService = concurrencyService; _constantRatePump = constantRatePump; _log = loggerFactory.Create(typeof(SpotTilePricingViewModel)); _priceSubscription = new SerialDisposable(); Bid = oneWayPriceFactory(Direction.SELL, this); Ask = oneWayPriceFactory(Direction.BUY, this); Notional = "1000000"; DealtCurrency = currencyPair.BaseCurrency; SpotDate = "SP"; IsSubscribing = true; SubscribeForPrices(); }
internal AudioPlayer() { this.audioPlayerCallback = new DummyMediaPlayerCallback(); this.videoPlayerCallback = new DummyMediaPlayerCallback(); this.currentCallback = new DummyMediaPlayerCallback(); this.finishSubscription = new SerialDisposable(); this.gate = new SemaphoreSlim(1, 1); this.playbackState = new BehaviorSubject<AudioPlayerState>(AudioPlayerState.None); this.PlaybackState = this.playbackState.DistinctUntilChanged(); this.loadedSong = new BehaviorSubject<Song>(null); this.TotalTime = this.loadedSong.Select(x => x == null ? TimeSpan.Zero : x.Duration); this.currentTimeChangedFromOuter = new Subject<TimeSpan>(); var conn = Observable.Interval(TimeSpan.FromMilliseconds(300), RxApp.TaskpoolScheduler) .CombineLatest(this.PlaybackState, (l, state) => state) .Where(x => x == AudioPlayerState.Playing) .Select(_ => this.CurrentTime) .Merge(this.currentTimeChangedFromOuter) .DistinctUntilChanged(x => x.TotalSeconds) .Publish(TimeSpan.Zero); conn.Connect(); this.CurrentTimeChanged = conn; }
protected override IEnumerable<IDisposable> Main() { disposable = new SerialDisposable(); UpdateFeed(); yield return disposable; }
public ViewModelViewHost() { this.currentView = new SerialDisposable(); this.viewContract = this .WhenAnyObservable(x => x.ViewContractObservable) .ToProperty(this, x => x.ViewContract, scheduler: RxApp.MainThreadScheduler); this.Initialize(); }
/// <summary> /// Uses the double-indirection pattern to assign the disposable returned by the specified <paramref name="factory"/> /// to the <see cref="SerialDisposable.Disposable"/> property of the specified <paramref name="disposable"/>. /// </summary> /// <remarks> /// The double-indirection pattern avoids a race condition that can occur when the <paramref name="factory"/> /// has a side-effect that causes the <see cref="SerialDisposable.Disposable"/> property of the specified /// <paramref name="disposable"/> to be assigned before the <paramref name="factory"/> returns its disposable. /// This pattern ensures that the disposable returned by the <paramref name="factory"/> does not replace the /// disposable that was assigned by the <paramref name="factory"/>. /// </remarks> /// <param name="disposable">The object to which the disposable returned by the specified <paramref name="factory"/> is assigned.</param> /// <param name="factory">Returns an <see cref="IDisposable"/> that is assigned to the specified <paramref name="disposable"/>.</param> /// <seealso href="http://social.msdn.microsoft.com/Forums/en-IE/rx/thread/4e15feae-9c4c-4962-af32-95dde1420dda#4d5fe8c8-e5e8-4ee7-93ca-b48b6a56b8af"> /// Double indirection pattern example in Rx /// </seealso> public static void SetDisposableIndirectly(this SerialDisposable disposable, Func <IDisposable> factory) { Contract.Requires(disposable != null); Contract.Requires(factory != null); var indirection = new SingleAssignmentDisposable(); disposable.Disposable = indirection; indirection.Disposable = factory(); }
public static IDisposable Schedule(this IScheduler scheduler, ILiveValue<TimeSpan> interval, Action action) { var startTime = HiResTimer.Now(); var gate = new object(); var hasValue = false; var cancelable = new SerialDisposable(); var id = 0UL; var observer = interval.CreateObserver( o => Publish.OnConsume( () => { // get new interval var state = o.GetState(); // work out interval from here var timeSpan = TimeSpan.Zero; if (state.Status.IsConnected()) { timeSpan = state.NewValue - HiResTimer.ToTimeSpan(HiResTimer.Now() - startTime); if (timeSpan < TimeSpan.Zero) timeSpan = TimeSpan.Zero; } // adapted from Observable.Throttle() ulong currentid; lock (gate) { hasValue = true; id += 1UL; currentid = id; } var timer = new SingleAssignmentDisposable(); cancelable.Disposable = timer; timer.Disposable = scheduler.Schedule( timeSpan, () => { lock (gate) { if (hasValue && (id == currentid)) action(); hasValue = false; } }); }) ); interval.Subscribe(observer); return new CompositeDisposable(new IDisposable[] { observer, cancelable }); }
public GoogleDriveExerciseDocumentService( ILoggerService loggerService, IConnectionResultHandler connectionResultHandler) { Ensure.ArgumentNotNull(loggerService, nameof(loggerService)); Ensure.ArgumentNotNull(connectionResultHandler, nameof(connectionResultHandler)); this.logger = loggerService.GetLogger(this.GetType()); this.connectionResultHandler = connectionResultHandler; this.exerciseDocument = new BehaviorSubject<string>(null); this.sync = new object(); this.connectedDisposable = new SerialDisposable(); }
public ModalDialogContext(string title = null) { var activeView = new SerialDisposable(); ModalDialogView dialog = null;// new ModalDialogView(); var dispatcher = Application.Current.Dispatcher; //var dispatcher = dialog.Dispatcher; dispatcher.BeginInvoke(() => { dialog = new ModalDialogView(); if (!disposables.IsDisposed) { disposables.Add( Disposable.Create( () => dispatcher.BeginInvoke( ()=>dialog.Close() ) ) ); dialog.Header = title; dialog.Owner = Application.Current.MainWindow; dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner; dialog.SizeToContent = SizeToContent.WidthAndHeight; dialog.ShowInTaskbar = false; dialog.ShowDialog(); activeView.Dispose(); } }); var presenter = ViewPresenter.Create(view => { var disp = new CompositeDisposable(); activeView.Disposable = disp; dispatcher.BeginInvoke(()=>{ dbg.Assert(dialog != null); if (!disp.IsDisposed) { dbg.Assert(dialog.Content == null); dialog.Content = view; var header = NavigationContext.GetTitle(view); dialog.Header = header ?? title; disp.Add( Disposable.Create(() => { dispatcher.BeginInvoke(() => { dbg.Assert(dialog.Content == view); dialog.Header = title; dialog.Content = null; var d = view as IDisposable; if (d != null) { d.Dispose(); } }); })); } }); return disp; }); container.RegisterInstance<IViewPresenter>(presenter); }
public static IDisposable handleViewActivation(Func<IEnumerable<IDisposable>> block, Tuple<IObservable<Unit>, IObservable<Unit>> activation) { var viewDisposable = new SerialDisposable(); return new CompositeDisposable( // Activation activation.Item1.Subscribe(_ => { // NB: We need to make sure to respect ordering so that the cleanup // happens before we invoke block again viewDisposable.Disposable = Disposable.Empty; viewDisposable.Disposable = new CompositeDisposable(block()); }), // Deactivation activation.Item2.Subscribe(_ => { viewDisposable.Disposable = Disposable.Empty; }), viewDisposable); }
public static IDisposable WhenActivated(this IViewFor This, Func<IEnumerable<IDisposable>> block) { var activationFetcher = activationFetcherCache.Get(This.GetType()); if (activationFetcher == null) { throw new ArgumentException( String.Format( "Don't know how to detect when {0} is activated/deactivated, you may need to implement IActivationForViewFetcher", This.GetType().FullName)); } var activationEvents = activationFetcher.GetActivationForView(This); var viewDisposable = new SerialDisposable(); return new CompositeDisposable( activationEvents.Item1.Subscribe(_ => viewDisposable.Disposable = new CompositeDisposable(block())), activationEvents.Item2.Subscribe(_ => viewDisposable.Disposable = Disposable.Empty), handleViewModelActivation(This, activationEvents), viewDisposable); }
public DeviceView(IUnityContainer container, DeviceViewModel vm) { this.DataContext = vm; InitializeComponent(); var actView = new SerialDisposable(); disposables.Add( vm.GetPropertyChangedEvents(m => m.Current) .ObserveOnDispatcher() .Subscribe(state => { switch (state) { case DeviceViewModel.States.Loading: content.Content = new ProgressView(LocalDevice.instance.loading); break; case DeviceViewModel.States.Error: content.Content = new ErrorView(vm.ErrorMessage); break; default: actView.Disposable = null; content.Content = deviceView; break; }; }) ); }
public void when_sliding_timeout_then_only_receives_final_window() { int TimeoutSeconds = 5; var clock = Clock.Default; var ticks = new SerialDisposable(); var timeout = new SerialDisposable(); var closer = new Subject<Unit>(); var timeouts = 0; ticks.Disposable = clock.Tick .Window(TimeSpan.FromSeconds(TimeoutSeconds)) .Subscribe(window => timeout.Disposable = window.Subscribe(_ => { }, () => timeouts++)); Thread.Sleep(2000); ticks.Disposable = clock.Tick .Window(TimeSpan.FromSeconds(TimeoutSeconds)) .Subscribe(window => timeout.Disposable = window.Subscribe(_ => { }, () => timeouts++)); Thread.Sleep(6000); Console.WriteLine(timeouts); }
public MainActivity() { this.resultResolutionSubject = new SerialDisposable<Subject<bool>>(); }
public override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); bool isReturningFromSelectorPage = (e.NavigationMode == NavigationMode.Back && e.IsNavigationInitiator); if (isReturningFromSelectorPage) { return; } changedProperties = new List<string>(); string[] dayNames = CultureInfo.CurrentCulture.DateTimeFormat.DayNames; updateDisposable = new SerialDisposable(); ShowBackgroundScheduleOptions = !deviceInformationService.IsLowEndDevice; ForegroundUpdateOptions = new[] { TimeSpan.Zero, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(15) }.Select(CreateUpdateInterval).ToList(); BackgroundUpdateOptions = new[] { TimeSpan.Zero, TimeSpan.FromMinutes(30), TimeSpan.FromHours(1), TimeSpan.FromHours(6), TimeSpan.FromDays(1) }.Select(CreateUpdateInterval).ToList(); }
public void Return_DisposedAfterNext() { var scheduler = new TestScheduler(); var d = new SerialDisposable(); var xs = Observable.Return(42, scheduler); var res = scheduler.CreateObserver<int>(); scheduler.ScheduleAbsolute(100, () => d.Disposable = xs.Subscribe( x => { d.Dispose(); res.OnNext(x); }, res.OnError, res.OnCompleted ) ); scheduler.Start(); res.Messages.AssertEqual( OnNext(101, 42) ); }
static IDisposable handleViewModelActivation(IViewFor view, IObservable<bool> activation) { var vmDisposable = new SerialDisposable(); var viewVmDisposable = new SerialDisposable(); return new CompositeDisposable( // Activation activation.Subscribe(activated => { if (activated) { viewVmDisposable.Disposable = view.WhenAnyValue(x => x.ViewModel) .Select(x => x as ISupportsActivation) .Subscribe(x => { // NB: We need to make sure to respect ordering so that the cleanup // happens before we activate again vmDisposable.Disposable = Disposable.Empty; if (x != null) { vmDisposable.Disposable = x.Activator.Activate(); } }); } else { viewVmDisposable.Disposable = Disposable.Empty; vmDisposable.Disposable = Disposable.Empty; } }), vmDisposable, viewVmDisposable); }
static IDisposable handleViewActivation(Func<IEnumerable<IDisposable>> block, IObservable<bool> activation) { var viewDisposable = new SerialDisposable(); return new CompositeDisposable( // Activation activation.Subscribe(activated => { // NB: We need to make sure to respect ordering so that the cleanup // happens before we invoke block again viewDisposable.Disposable = Disposable.Empty; if(activated) { viewDisposable.Disposable = new CompositeDisposable(block()); } }), viewDisposable); }
/// <summary> /// Creates an instance of the <see cref="SerialDisposable{T}"/> class. /// </summary> public SerialDisposable() { this.disposable = new SerialDisposable(); }
public void SerialDisposable_Dispose() { var disp = false; var m = new SerialDisposable(); var d = Disposable.Create(() => { disp = true; }); m.Disposable = d; Assert.AreSame(d, m.Disposable); Assert.IsFalse(disp); m.Dispose(); Assert.IsTrue(m.IsDisposed); Assert.IsTrue(disp); //Assert.IsNull(m.Disposable); // BREAKING CHANGE v2 > v1.x - Undefined behavior after disposal. }
static IDisposable handleViewModelActivation(IViewFor view, Tuple<IObservable<Unit>, IObservable<Unit>> activation) { var vm = view.ViewModel as ISupportsActivation; var disp = new SerialDisposable() {Disposable = (vm != null ? vm.Activator.Activate() : Disposable.Empty)}; var latestVm = Observable.Merge( activation.Item1.Select(_ => view.WhenAnyValue(x => x.ViewModel)), activation.Item2.Select(_ => Observable.Never<object>().StartWith(default(object)))) .Switch() .Select(x => x as ISupportsActivation); return new CompositeDisposable( disp, latestVm.Subscribe(x => disp.Disposable = (x != null ? x.Activator.Activate() : Disposable.Empty))); }
public void SerialDisposable_ReplaceBeforeDispose() { var disp1 = false; var disp2 = false; var m = new SerialDisposable(); var d1 = Disposable.Create(() => { disp1 = true; }); m.Disposable = d1; Assert.AreSame(d1, m.Disposable); Assert.IsFalse(disp1); var d2 = Disposable.Create(() => { disp2 = true; }); m.Disposable = d2; Assert.AreSame(d2, m.Disposable); Assert.IsTrue(disp1); Assert.IsFalse(disp2); }
/// <summary> /// Creates a new monitor for system clock changes with the specified polling frequency. /// </summary> /// <param name="period">Polling frequency for system clock changes.</param> public PeriodicTimerSystemClockMonitor(TimeSpan period) { _period = period; _timer = new SerialDisposable(); }
public override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); Disposables.Add(addJobsSubscrition = new SerialDisposable()); AddJobsCommand = CreateCommand(new ObservableCommand(CanAddJobs()), OnAddJobs); SelectAllJobsCommand = CreateCommand(new ObservableCommand(), OnSelectAllJobs); FilterJobsCommand = CreateCommand(new ObservableCommand(), OnFilterJobs); Disposables.Add(this.GetPropertyValues(x => x.FilterText) .Where(f => f != null && Jobs.Filter != f) .Sample(TimeSpan.FromMilliseconds(200), schedulerAccessor.UserInterface) .Select(filter => Observable.ToAsync(() => Jobs.Filter = filter, schedulerAccessor.Background)()) .Switch() .ObserveOn(schedulerAccessor.UserInterface) .Subscribe(_ => State = (Jobs.Count == 0) ? AddJobsViewState.NoResults : AddJobsViewState.Results)); SelectedJobs = new ObservableCollection<Job>(); var query = e.Uri.GetQueryValues(); if (!query.ContainsKey(BuildServerIdKey)) { navigationService.GoBack(); return; } IsSelectionEnabled = true; int buildServerId = Int32.Parse(query[BuildServerIdKey]); StartLoading(Strings.FindingJobsStatusMessage); BuildServer = jobRepository.GetBuildServer(buildServerId); this.State = AddJobsViewState.Loading; jobProviderFactory .Get(BuildServer.Provider) .GetJobsObservableAsync(BuildServer) .Select(jobs => RemoveExistingJobs(BuildServer, jobs)) .Select(jobs => jobs.Select(CreateAvailableJob) .OrderBy(j => j.Job.Name) .ToList() ) .ObserveOn(schedulerAccessor.UserInterface) .Finally(StopLoading) .Subscribe(loadedJobs => { existingJobCount = jobController.GetJobs().Count; allJobs = loadedJobs; Jobs = new FilteredObservableCollection<AvailableJob>(loadedJobs, FilterJob, schedulerAccessor.UserInterface); State = (Jobs.Count > 0) ? AddJobsViewState.Results : AddJobsViewState.NoResults; }, ex => { ErrorDescription = WebExceptionService.GetDisplayMessage(ex); State = AddJobsViewState.Error; }); }
static IDisposable handleViewModelActivation(IViewFor view, Tuple<IObservable<Unit>, IObservable<Unit>> activation) { var vmDisposable = new SerialDisposable(); return new CompositeDisposable( // Activation activation.Item1 .Select(_ => view.WhenAnyValue(x => x.ViewModel)) .Switch() .Select(x => x as ISupportsActivation) .Subscribe(x => { // NB: We need to make sure to respect ordering so that the cleanup // happens before we activate again vmDisposable.Disposable = Disposable.Empty; if(x != null) { vmDisposable.Disposable = x.Activator.Activate(); } }), // Deactivation activation.Item2.Subscribe(_ => { vmDisposable.Disposable = Disposable.Empty; }), vmDisposable); }
/// <summary> /// Fires a stream of RoleIds when you should reload. /// This happens whenever an Observer is active and the RoleId has changed. /// </summary> /// <returns> /// An Observable that fires the RoleId whenever data should be updated. /// </returns> protected IObservable<Guid> SetupExecuteObservable() { var loadQuery = Manager.Context.RoleIdObservable; var combinedObservationStateChanges = this.ObservationState; //loadQuery.Subscribe(s => Debug.WriteLine(String.Format("{0} RoleId {1}", queryKey, s))); //combinedObservationStateChanges.Subscribe(s => Debug.WriteLine(String.Format("{0} ObservationState {1}", queryKey, s))); //See http://stackoverflow.com/questions/7716114/rx-window-join-groupjoin for explanation var loadQueryUpdatesWhileInactive = new ReplaySubject<Guid>(1); var disposer = new SerialDisposable(); //the getSwitch will //a) publish loadQueryUpdates if the observation state is active //b) track loadQueryUpdates when ObservationState = suspended, then publish the loadQueryUpdate once active Func<ObservationState, IObservable<ObservationState>, IObservable<Guid>, IObservable<Guid>> getSwitch = (observationStateUpdate, observationStateUpdates, loadQueryUpdates) => { //a) because the observationState is active publish the loadQueryUpdatesWhileInactive & the loadQueryUpdates if (observationStateUpdate == Common.Models.ObservationState.Active) { //Merge the loadQueryUpdatesWhileInactive with the loadQueryUpdates return loadQueryUpdatesWhileInactive.Merge(loadQueryUpdates); } //b) because the ObservationState is suspended: // setup loadQueryUpdatesWhileInactive to keep track of the loadQueryUpdates while inactive //dispose the last loadQueryUpdatesWhileInactive subscription loadQueryUpdatesWhileInactive.Dispose(); //setup loadQueryUpdatesWhileInactive to track 1 (the last) loadQuery update loadQueryUpdatesWhileInactive = new ReplaySubject<Guid>(1); //dispose the temporary subscription to loadQueryUpdates disposer.Disposable = //track loadQueryUpdates until the next observationStateUpdates loadQueryUpdates.TakeUntil(observationStateUpdates) .Subscribe(loadQueryUpdatesWhileInactive); //setup loadQueryUpdatesWhileInactive //return an Empty Guid Observable so that executeQuery does not publish anything return Observable.Empty<Guid>(); }; //Create an Observable that fires the RoleId whenever data should be updated //The logic for when it should fire is defined in the getSwitch var executeQuery = combinedObservationStateChanges.DistinctUntilChanged() //whenever the combineObservationState changes .Publish(observationStateUpdates => loadQuery //publish the observationStateUpdates .Publish(loadQueryUpdates => //publish the loadQueryUpdates observationStateUpdates.Select( //select according to the getSwitch logic observationStateUpdate => getSwitch(observationStateUpdate, observationStateUpdates, loadQueryUpdates)))) .Switch() .Throttle(new TimeSpan(0, 0, 0, 0, 200));//Throttle for .2 second so it does not execute too often executeQuery.Subscribe(s => Debug.WriteLine(String.Format("Load data for {0} with RoleId {1}", GetType(), s))); return executeQuery; }
public void SerialDisposable_Ctor_Prop() { var m = new SerialDisposable(); Assert.IsNull(m.Disposable); }
static void Impl(int disposeAt) { var rand = new Random(); var s = new SerialDisposable(); Console.Write("Dispose @ = {0} - ", disposeAt); if (disposeAt == 0) { s.Dispose(); Console.Write("{SD} "); } if (disposeAt == 1) { var sleep = rand.Next(0, 5) > 1 /* 60% chance */ ? rand.Next(2, 1000) : 0; ThreadPool.QueueUserWorkItem(_ => { Helpers.SleepOrSpin(sleep); s.Dispose(); Console.Write("{SD} "); }); } var n = rand.Next(0, 1000); var cd = new CountdownEvent(n); var ds = Enumerable.Range(0, n).Select(_ => Disposable.Create(() => cd.Signal())).ToArray(); var m = rand.Next(1, 100); var jobs = ds.GroupBy(_ => rand.Next() % m).Select(Enumerable.ToList).ToList(); Console.Write("N = {0}, M = {1} - ", n, m); var done = new CountdownEvent(jobs.Count); foreach (var job in jobs) { var sleep = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0; var sleepAt = Enumerable.Range(0, rand.Next(0, job.Count) / rand.Next(1, 100)).ToArray(); var sleeps = sleepAt.Select(_ => rand.Next(0, 50)).ToArray(); var rem = rand.Next(0, 3) == 0; /* 33% chance */ var remAt = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0; var mine = job; ThreadPool.QueueUserWorkItem(_ => { Helpers.SleepOrSpin(sleep); var j = 0; foreach (var d in mine) { if (sleepAt.Contains(j)) Helpers.SleepOrSpin(sleeps[j]); s.Disposable = d; Console.Write("+"); j++; } done.Signal(); }); } done.Wait(); if (disposeAt == 2) { s.Dispose(); Console.Write("{SD} "); } cd.Wait(); Console.WriteLine("."); }
public void SerialDisposable_ReplaceAfterDispose() { var disp1 = false; var disp2 = false; var m = new SerialDisposable(); m.Dispose(); Assert.IsTrue(m.IsDisposed); var d1 = Disposable.Create(() => { disp1 = true; }); m.Disposable = d1; Assert.IsNull(m.Disposable); // CHECK Assert.IsTrue(disp1); var d2 = Disposable.Create(() => { disp2 = true; }); m.Disposable = d2; Assert.IsNull(m.Disposable); // CHECK Assert.IsTrue(disp2); }
public override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); bool isReturningFromSelectorPage = (e.NavigationMode == NavigationMode.Back && e.IsNavigationInitiator); if (isReturningFromSelectorPage) { return; } changedProperties = new List<string>(); string[] dayNames = CultureInfo.CurrentCulture.DateTimeFormat.DayNames; updateDisposable = new SerialDisposable(); NotificationDays = applicationSettings.NotificationDays .Select(d => dayNames[(int) d%dayNames.Length]) .ToList(); NotificationStart = DateTime.Today + applicationSettings.NotificationStart; NotificationEnd = DateTime.Today + applicationSettings.NotificationEnd; }
public void SerialRxOfficial() { var d = new SerialDisposable(); d.IsDisposed.IsFalse(); var id1 = new IdDisp(1); var id2 = new IdDisp(2); var id3 = new IdDisp(3); // dispose first d.Dispose(); d.IsDisposed.IsTrue(); d.Disposable = id1; id1.IsDisposed.IsTrue(); d.Disposable = id2; id2.IsDisposed.IsTrue(); d.Disposable = id3; id3.IsDisposed.IsTrue(); // normal flow d = new SerialDisposable(); id1 = new IdDisp(1); id2 = new IdDisp(2); id3 = new IdDisp(3); d.Disposable = id1; id1.IsDisposed.IsFalse(); d.Dispose(); id1.IsDisposed.IsTrue(); d.Disposable = id2; id2.IsDisposed.IsTrue(); d.Disposable = id3; id3.IsDisposed.IsTrue(); // exception flow d = new SerialDisposable(); id1 = new IdDisp(1); id2 = new IdDisp(2); id3 = new IdDisp(3); d.Disposable = id1; id1.IsDisposed.IsFalse(); d.Disposable = id2; id1.IsDisposed.IsTrue(); id2.IsDisposed.IsFalse(); d.Disposable = id3; id2.IsDisposed.IsTrue(); id3.IsDisposed.IsFalse(); d.Dispose(); id3.IsDisposed.IsTrue(); // null d = new SerialDisposable(); id1 = new IdDisp(1); d.Disposable = null; d.Dispose(); d.Disposable = null; }
public RoutedViewHost () { this.ViewContractObservable = Observable.Return<string> (null); this.titleUpdater = new SerialDisposable (); this.WhenActivated ( d => { d (this .WhenAnyValue (x => x.Router) .Where (x => x != null && x.NavigationStack.Count > 0 && this.ViewControllers.Length == 0) .Subscribe (x => { this.routerInstigated = true; NSViewController view = null; foreach (var viewModel in x.NavigationStack) { view = this.ResolveView (this.Router.GetCurrentViewModel (), null); this.PushViewController (view, false); } this.titleUpdater.Disposable = this.Router.GetCurrentViewModel () .WhenAnyValue (y => y.UrlPathSegment) .Subscribe (y => view.NavigationItem.Title = y); this.routerInstigated = false; })); d (this .WhenAnyValue (x => x.Router) .Where (x => x != null) .Select (x => x.NavigationStack.ItemsAdded) .Switch () .Where (x => x != null) .Select (contract => new { View = this.ResolveView (this.Router.GetCurrentViewModel (), /*contract*/null), Animate = this.Router.NavigationStack.Count > 1 }) .Subscribe (x => { if (this.routerInstigated) { return; } this.titleUpdater.Disposable = this.Router.GetCurrentViewModel () .WhenAnyValue (y => y.UrlPathSegment) .Subscribe (y => x.View.NavigationItem.Title = y); this.routerInstigated = true; // super important that animate is false if it's the first view being pushed, otherwise iOS gets hella confused // and calls PushViewController twice this.PushViewController (x.View, x.Animate); this.routerInstigated = false; })); d (this .WhenAnyObservable (x => x.Router.NavigationStack.Changed) .Where (x => x.Action == NotifyCollectionChangedAction.Reset) .Subscribe (_ => { this.routerInstigated = true; this.PopToRootViewController (true); this.routerInstigated = false; })); d (this .WhenAnyObservable (x => x.Router.NavigateBack) .Subscribe (x => { this.routerInstigated = true; this.PopViewController (true); this.routerInstigated = false; })); }); }