Beispiel #1
0
 protected void NotifyCollectionModification(string propName, object value, CollectionModification modification)
 {
     if (CollectionModified != null)
     {
         CollectionModified(this, new CollectionModifiedEventArgs()
         {
             PropertyName     = propName,
             Value            = value,
             ModificationType = modification
         });
     }
 }
Beispiel #2
0
        /// <summary>
        /// Changes the list according to the specified collection notification.
        /// </summary>
        /// <param name="value">A modification that indicates how the list must be changed.</param>
        public void OnNext(CollectionModification <T> value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            lock (gate)
            {
                EnsureNotDisposed();

                if (EnsureNotStopped())
                {
                    IList <T> values;

                    switch (value.Kind)
                    {
                    case CollectionModificationKind.Add:
                        values = value.Values;

                        for (int i = 0; i < values.Count; i++)
                        {
                            var item = values[i];

                            list.Add(item);

                            subject.OnNext(CollectionNotification.CreateOnAdded(item));
                        }
                        break;

                    case CollectionModificationKind.Remove:
                        values = value.Values;

                        for (int i = 0; i < values.Count; i++)
                        {
                            var item = values[i];

                            if (list.Remove(item))
                            {
                                subject.OnNext(CollectionNotification.CreateOnRemoved(item));
                            }
                        }
                        break;

                    case CollectionModificationKind.Clear:
                        list.Clear();

                        subject.OnNext(CollectionNotification.CreateOnCleared <T>());
                        break;
                    }
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Changes the dictionary according to the specified collection modification.
        /// </summary>
        /// <param name="value">A modification that indicates how the dictionary must be changed.</param>
        public void OnNext(CollectionModification <KeyValuePair <TKey, TValue> > value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            lock (gate)
            {
                EnsureNotDisposed();

                if (EnsureNotStopped())
                {
                    IList <KeyValuePair <TKey, TValue> > pairs;

                    switch (value.Kind)
                    {
                    case CollectionModificationKind.Add:
                        // value.Accept(this) is not used for additions because it calls the ICollection<KeyValuePair<TKey, TValue>>.Add implementation, which throws if the key already exists.
                        pairs = value.Values;

                        for (int i = 0; i < pairs.Count; i++)
                        {
                            SetInternal(pairs[i]);
                        }
                        break;

                    case CollectionModificationKind.Remove:
                        // value.Accept(this) is not used for removals because it calls the ICollection<KeyValuePair<TKey, TValue>>.Remove implementation, which compares keys and also compares values.
                        pairs = value.Values;

                        for (int i = 0; i < pairs.Count; i++)
                        {
                            var key = pairs[i].Key;

                            if (dictionary.Contains(key))
                            {
                                RemoveInternal(key);
                            }
                        }
                        break;

                    case CollectionModificationKind.Clear:
                        ClearInternal();
                        break;
                    }
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Identifies which items were changed, removed and added to the target collection
        /// when compared with the imported data and performs the necessary operations for
        /// the dependent data of the affected elements.
        /// </summary>
        /// <param name="importedDataCollection">The imported data collection which is used to update
        /// the <see cref="targetCollection"/>.</param>
        /// <param name="sourceFilePath">The source file path.</param>
        /// <returns>An <see cref="IEnumerable{T}"/> with affected objects.</returns>
        /// <exception cref="UpdateDataException">Thrown when:
        /// <list type="bullet">
        /// <item>duplicate items are being added to the <see cref="targetCollection"/>;</item>
        /// <item>duplicate items are found in the <paramref name="importedDataCollection"/>.</item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="importedDataCollection"/>
        /// is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">Thrown when <paramref name="importedDataCollection"/> contains
        /// <c>null</c> elements.</exception>
        private IEnumerable <IObservable> ModifyDataCollection(IEnumerable <TTargetData> importedDataCollection,
                                                               string sourceFilePath)
        {
            TTargetData[] importedObjects = importedDataCollection.ToArray();

            var modification = new CollectionModification(targetCollection, importedObjects, equalityComparer);

            var affectedObjects = new List <IObservable>();

            if (modification.HasUpdates())
            {
                affectedObjects.Add(targetCollection);
            }

            affectedObjects.AddRange(UpdateData(modification.ObjectsToBeUpdated.Values, importedObjects));
            affectedObjects.AddRange(RemoveData(modification.ObjectsToBeRemoved));
            targetCollection.Clear();
            targetCollection.AddRange(modification.GetModifiedCollection(), sourceFilePath);

            return(affectedObjects.Distinct(new ReferenceEqualityComparer <IObservable>()));
        }
        /// <summary>
        /// Converts <see cref="INotifyCollectionChanged.CollectionChanged"/> events into an observable sequence of <see cref="CollectionModification{T}"/>.
        /// </summary>
        /// <typeparam name="T">The object that provides notification information.</typeparam>
        /// <param name="source">An implementation of <see cref="INotifyCollectionChanged"/> that raises events when a collection changes.</param>
        /// <remarks>
        /// An <see cref="NotifyCollectionChangedAction.Add"/> event is projected into zero or more <see cref="CollectionModificationKind.Add"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Remove"/> event is projected into zero or more <see cref="CollectionModificationKind.Remove"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Move"/> event is ignored.
        /// A <see cref="NotifyCollectionChangedAction.Replace"/> event is projected into zero or more sequential
        /// <see cref="CollectionModificationKind.Remove"/> and <see cref="CollectionModificationKind.Add"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Reset"/> event is projected into a single <see cref="CollectionModificationKind.Clear"/> modification.
        /// </remarks>
        /// <returns>An observable sequence of <see cref="CollectionModification{T}"/> objects corresponding to raised events.</returns>
#else
        /// <summary>
        /// Converts <see cref="INotifyCollectionChanged.CollectionChanged"/> events into an observable sequence of <see cref="CollectionModification{T}"/>.
        /// </summary>
        /// <typeparam name="T">The object that provides notification information.</typeparam>
        /// <param name="source">An implementation of <see cref="INotifyCollectionChanged"/> that raises events when a collection changes.</param>
        /// <remarks>
        /// An <see cref="NotifyCollectionChangedAction.Add"/> event is projected into zero or more <see cref="CollectionModificationKind.Add"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Remove"/> event is projected into zero or more <see cref="CollectionModificationKind.Remove"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Replace"/> event is projected into zero or more sequential
        /// <see cref="CollectionModificationKind.Remove"/> and <see cref="CollectionModificationKind.Add"/> modifications.
        /// A <see cref="NotifyCollectionChangedAction.Reset"/> event is projected into a single <see cref="CollectionModificationKind.Clear"/> modification.
        /// </remarks>
        /// <returns>An observable sequence of <see cref="CollectionModification{T}"/> objects corresponding to raised events.</returns>
#endif
        public static IObservable <CollectionModification <T> > AsCollectionModifications <T>(this INotifyCollectionChanged source)
        {
            Contract.Requires(source != null);
            Contract.Ensures(Contract.Result <IObservable <CollectionModification <T> > >() != null);

            return(Observable.FromEventPattern <NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
                       eh => source.CollectionChanged += eh,
                       eh => source.CollectionChanged -= eh)
                   .SelectMany(e =>
            {
                var args = e.EventArgs;

                switch (args.Action)
                {
                case NotifyCollectionChangedAction.Add:
                    return Observable.Return(CollectionModification.CreateAdd(EnsureList <T>(args.NewItems)));

                case NotifyCollectionChangedAction.Remove:
                    return Observable.Return(CollectionModification.CreateRemove(EnsureList <T>(args.OldItems)));

#if !SILVERLIGHT
                case NotifyCollectionChangedAction.Move:
                    return Observable.Empty <CollectionModification <T> >();
#endif
                case NotifyCollectionChangedAction.Replace:
                    return Observable.Return(CollectionModification.CreateRemove(EnsureList <T>(args.OldItems)))
                    .Concat(Observable.Return(CollectionModification.CreateAdd(EnsureList <T>(args.NewItems))));

                case NotifyCollectionChangedAction.Reset:
                    return Observable.Return(CollectionModification.CreateClear <T>());

                default:
                    throw new InvalidOperationException();
                }
            }));
        }
 public void OnNext(CollectionModification <KeyValuePair <TKey, TValue> > value)
 {
 }
 /// <summary>
 /// Changes the dictionary according to the specified collection modification.  This method is not supported.
 /// </summary>
 /// <param name="value">A modification that indicates how the dictionary must be changed.</param>
 /// <exception cref="NotSupportedException">Attempted to set an item in a read-only dictionary.</exception>
 public void OnNext(CollectionModification <KeyValuePair <TKey, TValue> > value)
 {
     throw new NotSupportedException();
 }
Beispiel #8
0
 /// <summary>
 /// Changes the list according to the specified collection modification.  This method is not supported.
 /// </summary>
 /// <param name="value">A modification that indicates how the list must be changed.</param>
 /// <exception cref="NotSupportedException">Attempted to modify a read-only list.</exception>
 public void OnNext(CollectionModification <T> value)
 {
     throw new NotSupportedException();
 }
Beispiel #9
0
 public void OnNext(CollectionModification <T> value)
 {
 }
        internal static ReadOnlyListSubject <TResult> CollectInternal <TResult>(
            this FileSystemWatcher watcher,
            bool composited,
            Func <IObservable <CollectionNotification <string> >, IObservable <CollectionModification <TResult> > > selector,
            IScheduler scheduler)
        {
            Contract.Requires(watcher != null);
            Contract.Requires(selector != null);
            Contract.Requires(scheduler != null);
            Contract.Ensures(Contract.Result <ReadOnlyListSubject <TResult> >() != null);

            var existing = Directory
                           .EnumerateFiles(
                watcher.Path,
                watcher.Filter,
                watcher.IncludeSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);

            var changes = watcher
                          .Watch(WatcherChangeTypes.Created | WatcherChangeTypes.Deleted | WatcherChangeTypes.Renamed)
                          .SelectMany(notification => notification.Change == WatcherChangeTypes.Created
          ? Observable.Return(CollectionModification.CreateAdd(notification.FullPath))
          : notification.Change == WatcherChangeTypes.Deleted
            ? Observable.Return(CollectionModification.CreateRemove(notification.FullPath))
            : Observable.Return(CollectionModification.CreateRemove(notification.OldFullPath)).Concat(Observable.Return(CollectionModification.CreateAdd(notification.FullPath))));

            if (composited)
            {
                changes = changes.Finally(watcher.Dispose);
            }

            return(existing.ToObservable(scheduler).Collect(changes.ObserveOn(scheduler), selector, StringComparer.OrdinalIgnoreCase));
        }