Ejemplo n.º 1
0
        public IObservable <IChangeSet <TDestination, TLeftKey> > Run()
        {
            return(Observable.Create <IChangeSet <TDestination, TLeftKey> >(observer =>
            {
                var locker = new object();

                //create local backing stores
                var leftCache = _left.Synchronize(locker).AsObservableCache(false);
                var rightCache = _right.Synchronize(locker).ChangeKey(_rightKeySelector).AsObservableCache(false);

                //joined is the final cache
                var joinedCache = new LockFreeObservableCache <TDestination, TLeftKey>();

                var leftLoader = leftCache.Connect()
                                 .Subscribe(changes =>
                {
                    joinedCache.Edit(innerCache =>
                    {
                        changes.ForEach(change =>
                        {
                            switch (change.Reason)
                            {
                            case ChangeReason.Add:
                            case ChangeReason.Update:
                                //Update with left (and right if it is presents)
                                var left = change.Current;
                                var right = rightCache.Lookup(change.Key);
                                innerCache.AddOrUpdate(_resultSelector(change.Key, left, right), change.Key);
                                break;

                            case ChangeReason.Remove:
                                //remove from result because a left value is expected
                                innerCache.Remove(change.Key);
                                break;

                            case ChangeReason.Refresh:
                                //propagate upstream
                                innerCache.Refresh(change.Key);
                                break;
                            }
                        });
                    });
                });

                var rightLoader = rightCache.Connect()
                                  .Subscribe(changes =>
                {
                    joinedCache.Edit(innerCache =>
                    {
                        changes.ForEach(change =>
                        {
                            var right = change.Current;
                            var left = leftCache.Lookup(change.Key);

                            switch (change.Reason)
                            {
                            case ChangeReason.Add:
                            case ChangeReason.Update:
                                {
                                    if (left.HasValue)
                                    {
                                        //Update with left and right value
                                        innerCache.AddOrUpdate(_resultSelector(change.Key, left.Value, right),
                                                               change.Key);
                                    }
                                    else
                                    {
                                        //remove if it is already in the cache
                                        innerCache.Remove(change.Key);
                                    }
                                }
                                break;

                            case ChangeReason.Remove:
                                {
                                    if (left.HasValue)
                                    {
                                        //Update with no right value
                                        innerCache.AddOrUpdate(
                                            _resultSelector(change.Key, left.Value, Optional <TRight> .None),
                                            change.Key);
                                    }
                                    else
                                    {
                                        //remove if it is already in the cache
                                        innerCache.Remove(change.Key);
                                    }
                                }
                                break;

                            case ChangeReason.Refresh:
                                //propagate upstream
                                innerCache.Refresh(change.Key);
                                break;
                            }
                        });
                    });
                });


                return new CompositeDisposable(
                    joinedCache.Connect().NotEmpty().SubscribeSafe(observer),
                    leftCache,
                    rightCache,
                    leftLoader,
                    joinedCache,
                    rightLoader);
            }));
        }
Ejemplo n.º 2
0
        public IObservable <IChangeSet <TDestination, TLeftKey> > Run()
        {
            return(Observable.Create <IChangeSet <TDestination, TLeftKey> >(observer =>
            {
                var locker = new object();

                //create local backing stores
                var leftCache = _left.Synchronize(locker).AsObservableCache(false);
                var rightCache = _right.Synchronize(locker).ChangeKey(_rightKeySelector).AsObservableCache(false);

                //joined is the final cache
                var joinedCache = new LockFreeObservableCache <TDestination, TLeftKey>();

                var leftLoader = leftCache.Connect()
                                 .Subscribe(changes =>
                {
                    joinedCache.Edit(innerCache =>
                    {
                        changes.ForEach(change =>
                        {
                            var left = change.Current;
                            var right = rightCache.Lookup(change.Key);

                            switch (change.Reason)
                            {
                            case ChangeReason.Add:
                            case ChangeReason.Update:
                                {
                                    if (right.HasValue)
                                    {
                                        innerCache.AddOrUpdate(_resultSelector(change.Key, left, right.Value), change.Key);
                                    }
                                    else
                                    {
                                        innerCache.Remove((TLeftKey)change.Key);
                                    }
                                    break;
                                }

                            case ChangeReason.Remove:
                                innerCache.Remove((TLeftKey)change.Key);
                                break;

                            case ChangeReason.Refresh:
                                //propagate upstream
                                innerCache.Refresh((TLeftKey)change.Key);
                                break;
                            }
                        });
                    });
                });

                var rightLoader = rightCache.Connect()
                                  .Subscribe(changes =>
                {
                    joinedCache.Edit(innerCache =>
                    {
                        changes.ForEach(change =>
                        {
                            var right = change.Current;
                            var left = leftCache.Lookup(change.Key);

                            switch (change.Reason)
                            {
                            case ChangeReason.Add:
                            case ChangeReason.Update:
                                {
                                    if (left.HasValue)
                                    {
                                        innerCache.AddOrUpdate(_resultSelector(change.Key, left.Value, right), change.Key);
                                    }
                                    else
                                    {
                                        innerCache.Remove(change.Key);
                                    }
                                }
                                break;

                            case ChangeReason.Remove:
                                {
                                    innerCache.Remove(change.Key);;
                                }
                                break;

                            case ChangeReason.Refresh:
                                //propagate upstream
                                innerCache.Refresh(change.Key);
                                break;
                            }
                        });
                    });
                });

                return new CompositeDisposable(
                    joinedCache.Connect().NotEmpty().SubscribeSafe(observer),
                    leftCache,
                    rightCache,
                    leftLoader,
                    rightLoader,
                    joinedCache);
            }));
        }