| File: System\Data\DataViewListener.cs | Web Access |
| Project: src\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj (System.Data.Common) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace System.Data { internal sealed class DataViewListener { private readonly WeakReference _dvWeak; private DataTable? _table; private Index? _index; /// <summary><see cref="DataView.ObjectID"/></summary> internal readonly int _objectID; internal DataViewListener(DataView dv) { _objectID = dv.ObjectID; _dvWeak = new WeakReference(dv); } private void ChildRelationCollectionChanged(object? sender, CollectionChangeEventArgs e) { DataView? dv = (DataView?)_dvWeak.Target; if (dv != null) { dv.ChildRelationCollectionChanged(sender, e); } else { CleanUp(true); } } private void ParentRelationCollectionChanged(object? sender, CollectionChangeEventArgs e) { DataView? dv = (DataView?)_dvWeak.Target; if (dv != null) { dv.ParentRelationCollectionChanged(sender, e); } else { CleanUp(true); } } private void ColumnCollectionChanged(object? sender, CollectionChangeEventArgs e) { DataView? dv = (DataView?)_dvWeak.Target; if (dv != null) { dv.ColumnCollectionChangedInternal(sender, e); } else { CleanUp(true); } } /// <summary> /// Maintain the DataView before <see cref="DataView.ListChanged"/> is raised. /// </summary> internal void MaintainDataView(ListChangedType changedType, DataRow? row, bool trackAddRemove) { DataView? dv = (DataView?)_dvWeak.Target; if (dv != null) { dv.MaintainDataView(changedType, row, trackAddRemove); } else { CleanUp(true); } } internal void IndexListChanged(ListChangedEventArgs e) { DataView? dv = (DataView?)_dvWeak.Target; if (dv != null) { dv.IndexListChangedInternal(e); } else { CleanUp(true); } } internal void RegisterMetaDataEvents(DataTable? table) { Debug.Assert(null == _table, "DataViewListener already registered table"); _table = table; if (table != null) { // actively remove listeners without a target RegisterListener(table); // start listening to events var handlerCollection = new CollectionChangeEventHandler(ColumnCollectionChanged); table.Columns.ColumnPropertyChanged += handlerCollection; table.Columns.CollectionChanged += handlerCollection; var handlerChildRelation = new CollectionChangeEventHandler(ChildRelationCollectionChanged); ((DataRelationCollection.DataTableRelationCollection)(table.ChildRelations)).RelationPropertyChanged += handlerChildRelation; table.ChildRelations.CollectionChanged += handlerChildRelation; var handlerParentRelation = new CollectionChangeEventHandler(ParentRelationCollectionChanged); ((DataRelationCollection.DataTableRelationCollection)(table.ParentRelations)).RelationPropertyChanged += handlerParentRelation; table.ParentRelations.CollectionChanged += handlerParentRelation; } } internal void UnregisterMetaDataEvents() => UnregisterMetaDataEvents(true); private void UnregisterMetaDataEvents(bool updateListeners) { DataTable? table = _table; _table = null; if (table != null) { CollectionChangeEventHandler handlerCollection = new CollectionChangeEventHandler(ColumnCollectionChanged); table.Columns.ColumnPropertyChanged -= handlerCollection; table.Columns.CollectionChanged -= handlerCollection; CollectionChangeEventHandler handlerChildRelation = new CollectionChangeEventHandler(ChildRelationCollectionChanged); ((DataRelationCollection.DataTableRelationCollection)(table.ChildRelations)).RelationPropertyChanged -= handlerChildRelation; table.ChildRelations.CollectionChanged -= handlerChildRelation; CollectionChangeEventHandler handlerParentRelation = new CollectionChangeEventHandler(ParentRelationCollectionChanged); ((DataRelationCollection.DataTableRelationCollection)(table.ParentRelations)).RelationPropertyChanged -= handlerParentRelation; table.ParentRelations.CollectionChanged -= handlerParentRelation; if (updateListeners) { List<DataViewListener> listeners = table.GetListeners(); lock (listeners) { listeners.Remove(this); } } } } internal void RegisterListChangedEvent(Index index) { Debug.Assert(null == _index, "DataviewListener already registered index"); _index = index; if (null != index) { lock (index) { index.AddRef(); index.ListChangedAdd(this); } } } internal void UnregisterListChangedEvent() { Index? index = _index; _index = null; if (index != null) { lock (index) { index.ListChangedRemove(this); if (index.RemoveRef() <= 1) { index.RemoveRef(); } } } } private void CleanUp(bool updateListeners) { UnregisterMetaDataEvents(updateListeners); UnregisterListChangedEvent(); } private void RegisterListener(DataTable table) { List<DataViewListener> listeners = table.GetListeners(); lock (listeners) { for (int i = listeners.Count - 1; 0 <= i; --i) { DataViewListener listener = listeners[i]; if (!listener._dvWeak.IsAlive) { listeners.RemoveAt(i); listener.CleanUp(false); } } listeners.Add(this); } } } }