public void Weak_event_binding_shall_allow_expression_to_be_collected() { TestObject TestObject = new TestObject(); TestObject InnerTestObject = new TestObject(); TestObject.ObjectCollection.Add(InnerTestObject); (WeakReference, WeakReference) Create() { Func <TestObject, ObservableExpressionFactory.EventSink, string> CompiledExpression = ObservableExpressionFactory.Compile((TestObject test) => test.ObjectCollection[0].Property); ObservableExpressionFactory.EventSink Callback = new ObservableExpressionFactory.EventSink(delegate { }); CompiledExpression(TestObject, Callback); return(new WeakReference(CompiledExpression), new WeakReference(Callback)); } (WeakReference WeakExpression, WeakReference WeakCallback) = Create(); GC.Collect(); // ReSharper restore RedundantAssignment Assert.IsFalse(WeakExpression.IsAlive); Assert.IsFalse(WeakCallback.IsAlive); //throw event to let the weakdelegates remove themselves (for coverage) InnerTestObject.Property = "Hello, world"; TestObject.ObjectCollection.Clear(); }
private void AdapterCreationCallback(TSourceEnumerationItem sourceValue) { try { //Replace item with a newly created adapter var OldItem = this.items.First(_ => object.Equals(_.SourceValue, sourceValue)); ObservableExpressionFactory.EventSink EventSink = new ObservableExpressionFactory.EventSink((sender, e) => this.AdapterCreationCallback(sourceValue)); CachedValueCollectionItem NewItem = new CachedValueCollectionItem(sourceValue, this.adapter.adapterCreation(this.source, sourceValue, EventSink), EventSink); this.Replace(OldItem, NewItem); } catch (Exception) { // Something happend while converting and/or adding the item. Reset the colleciton and retry 'from scratch' this.adapter.NotifyItemUpdateFailed(this.source); } }
public CachedValueCollectionItem(TSourceEnumerationItem sourceValue, TTargetEnumerationItem targetValue, ObservableExpressionFactory.EventSink eventSink) { this.eventSink = eventSink; this.SourceValue = sourceValue; this.TargetValue = targetValue; }
public void Update(IEnumerable <TSourceEnumerationItem> values) { TSourceEnumerationItem[] Values = values != null?values.ToArray() : new TSourceEnumerationItem[0]; if (Values.Length > 0) { //First delete items to avoid unneeded move operations. save in arraqy to be able to modify the source collection foreach (CachedValueCollectionItem ItemToDelete in this.items.Where(item => Values.Any(value => object.Equals(value, item.SourceValue)) == false).ToArray()) { this.Remove(ItemToDelete); } ObservableCollection <CachedValueCollectionItem> OldValues = new ObservableCollection <CachedValueCollectionItem>(this.items.ToArray()); //Move existing entries to new locations and eventually add new entries for (int Index = 0; Index < Values.Length; Index++) { if (OldValues.Count > Index && object.Equals(OldValues[Index], Values[Index])) { //Item is still the same -> nothing to do DebugLogger.WriteLine(this, LoggingLevel.Verbose, () => $"Collection Update: index {Index} stays unchanged"); } else { //Search for the item. first we have to find the item in the cache to get the index. Skip already sorted entries to allow handling of equal objects in the same list int SearchIndex = OldValues.IndexOf(OldValues.Skip(Index).FirstOrDefault(_ => object.Equals(_.SourceValue, Values[Index]))); if (SearchIndex != -1) { //Found in the list if (Index != SearchIndex) { //-> move to front DebugLogger.WriteLine(this, LoggingLevel.Verbose, () => $"Collection Update: Move index {SearchIndex} to index {Index}"); this.Move(SearchIndex, Index); OldValues.Move(SearchIndex, Index); } else { //Position already matches -> do nothing } } else { //Not found -> must be new DebugLogger.WriteLine(this, LoggingLevel.Verbose, () => $"Collection Update: Add new item at index {Index}"); TSourceEnumerationItem SourceValue = Values[Index]; ObservableExpressionFactory.EventSink EventSink = new ObservableExpressionFactory.EventSink((sender, e) => this.AdapterCreationCallback(SourceValue)); CachedValueCollectionItem NewItem = new CachedValueCollectionItem(SourceValue, this.adapter.adapterCreation(this.source, SourceValue, EventSink), EventSink); this.Insert(Index, NewItem); OldValues.Insert(Index, NewItem); } } } } else { this.ClearItems(); } }