public ICommitContext Fill(IValueSource valueSource, Func <IValueSource, MappedObjectKeys> getKeyFunction, Func <T> createObject) { lock (_cache) { Init(true); CommitContext commitContext = new CommitContext(this); while (valueSource.Next()) { MappedObjectKeys keys = getKeyFunction(valueSource); if (_cache._itemsByKey.ContainsKey(keys)) { IFillAbleObject item = _cache._itemsByKey[keys].Value; if (item == null) { _cache._itemsByKey[keys] = new WeakReference <IFillAbleObject>(item = (IFillAbleObject)createObject()); ((System.ComponentModel.INotifyPropertyChanged)item).PropertyChanged += _cache.EntryValuePropertyChanged; } item.Fill(valueSource); commitContext.AddEntryToCommit((T)item); } else { IFillAbleObject newObject = (IFillAbleObject)createObject(); newObject.Fill(valueSource); _cache._itemsByKey.Add(keys, new WeakReference <IFillAbleObject>(newObject)); commitContext.AddEntryToCommit((T)newObject); ((System.ComponentModel.INotifyPropertyChanged)newObject).PropertyChanged += _cache.EntryValuePropertyChanged; } } return(commitContext); } }
private void AppendEntry(T item) { Init(false); IFillAbleObject fillableObject = (IFillAbleObject)item; if (fillableObject.State == State.Deleted) { lock (_deletedItems) { if (_deletedItems.Contains(item)) { return; } _deletedItems.Add(item); } ((System.ComponentModel.INotifyPropertyChanged)item).PropertyChanged += ItemsNotifyPropertyChanged; } else { lock (_items) { if (_items.Contains(item)) { return; } ((System.ComponentModel.INotifyPropertyChanged)item).PropertyChanged += ItemsNotifyPropertyChanged; if (_context.OrderExpressions == null || _context.OrderExpressions.Count == 0) { InsertAt(_items.Count, item); } else { #region Ordered Insert if (_items.Count == 0) { InsertAt(0, item); _expectedNextInsertIndex = 1; } else if ( (_items.Count == _expectedNextInsertIndex && _context.Compare(item, _items[_expectedNextInsertIndex - 1]) >= 0) || (_expectedNextInsertIndex == 0 && _context.Compare(item, _items[0]) <= 0) || (_expectedNextInsertIndex < _items.Count && _expectedNextInsertIndex > 0 && _context.Compare(item, _items[_expectedNextInsertIndex]) <= 0 && _context.Compare(item, _items[_expectedNextInsertIndex - 1]) >= 0) ) { InsertAt(_expectedNextInsertIndex++, item); } else { void binarySearch(int min, int max) { int spread = max - min; if (spread == 0) { InsertAt(_expectedNextInsertIndex = (_context.Compare(item, _items[min]) < 0 ? min : ++min), item); } else if (spread == 1) { InsertAt(_expectedNextInsertIndex = (_context.Compare(item, _items[min]) < 0 ? min : _context.Compare(item, _items[max]) < 0 ? max : ++max), item); } else { int mid = min + (spread / 2); int compare = _context.Compare(item, _items[mid]); if (compare == 0) { InsertAt(_expectedNextInsertIndex = mid, item); } else if (compare > 0) { binarySearch(mid, max); } else { binarySearch(min, mid); } } } binarySearch(0, _items.Count - 1); } #endregion } } } }
public void ReportEntryValueChanged(IFillAbleObject item) { if (_disableReportEntryValueChanged) { return; } Init(false); T obj = (T)item; bool match; try { match = _context.GetPredicateCompiled()(obj); } #if DEBUG && !NETCOREAPP1_0 catch (Exception ex) { if (!_isWeakCacheExceptionSent) { _isWeakCacheExceptionSent = true; System.Diagnostics.Trace.TraceError("Error while evaluating Predicate in PropertyChanged event. Predicate: {0}\nException:\n{1}", _context.GetPredicate(), ex); } else { throw; } #else catch { #endif match = false; } bool contains = item.State == State.Deleted ? _deletedItems.Contains(obj) : _items.Contains(obj); if (match && !contains) { AppendEntry(obj); } else if (!match && contains) { if (((IFillAbleObject)item).State == State.Deleted) { if (_deletedItems.Remove(obj)) { ((System.ComponentModel.INotifyPropertyChanged)item).PropertyChanged -= ItemsNotifyPropertyChanged; } return; } else { int index = _items.IndexOf(obj); if (index == -1) { return; } _items.RemoveAt(index); ((System.ComponentModel.INotifyPropertyChanged)item).PropertyChanged -= ItemsNotifyPropertyChanged; OnCollectionChanged(new System.Collections.Specialized.NotifyCollectionChangedEventArgs(System.Collections.Specialized.NotifyCollectionChangedAction.Remove, item, index)); } } }