Override Dictionary.Add

前端 未结 5 1915
星月不相逢
星月不相逢 2020-12-17 10:07

I need to know how to override the Add-method of a certain Dictionary in a certain static class. Any suggestions?

If it matters, the dictionary looks like this:

5条回答
  •  长情又很酷
    2020-12-17 10:43

    I went with CodesInChaos's solution. Since there's a bit of overhead involved in implementing IDictionary, here is a virtual implementation for general consumption. I'm including some comments and an example below for optional reading. Let me know if I should fix or improve something. I haven't done much testing, but it seems to work for overriding the add method.

    using System.Collections;
    using System.Collections.Generic;
    
    /// 
    /// Represents a collection of keys and values. This is an abstract base-class wrapping a  with 
    /// virtual method that can be overridden. This class can be used to override the default functionality of .
    /// 
    /// The type of the keys in the dictionary.
    /// The type of the values in the dictionary.
    public class VirtualDictionary : IDictionary
    {
        protected IDictionary wrappedDictionary;
    
        /// 
        /// Initializes a new instance of the  class that is empty, has the default initial capacity, and uses the default equality comparer for the key type.
        /// 
        public VirtualDictionary()
        {
            wrappedDictionary = new Dictionary();
        }
    
        /// 
        /// Initializes a new instance of the  class that is empty, has the specified initial capacity, and uses the default equality comparer for the key type.
        /// 
        /// The initial number of elements that the  can contain. is less than 0.
        public VirtualDictionary(int capacity)
        {
            wrappedDictionary = new Dictionary(capacity);
        }
    
        /// 
        /// Initializes a new instance of the  class that is empty, has the default initial capacity, and uses the specified .
        /// 
        /// The  implementation to use when comparing keys, or null to use the default  for the type of the key.
        public VirtualDictionary(IEqualityComparer comparer)
        {
            wrappedDictionary = new Dictionary(comparer);
        }
    
        /// 
        /// Initializes a new instance of the  class that is empty, has the specified initial capacity, and uses the specified .
        /// 
        /// The initial number of elements that the  can contain.The  implementation to use when comparing keys, or null to use the default  for the type of the key. is less than 0.
        public VirtualDictionary(int capacity, IEqualityComparer comparer)
        {
            wrappedDictionary = new Dictionary(capacity, comparer);
        }
    
        /// 
        /// Initializes a new instance of the  class that contains elements copied from the specified  and uses the default equality comparer for the key type.
        /// 
        /// The  whose elements are copied to the new . is null. contains one or more duplicate keys.
        public VirtualDictionary(IDictionary dictionary)
        {
            wrappedDictionary = new Dictionary(dictionary);
        }
    
        /// 
        /// Initializes a new instance of the  class that contains elements copied from the specified  and uses the specified .
        /// 
        /// The  whose elements are copied to the new .The  implementation to use when comparing keys, or null to use the default  for the type of the key. is null. contains one or more duplicate keys.
        public VirtualDictionary(IDictionary dictionary, IEqualityComparer comparer)
        {
            wrappedDictionary = new Dictionary(dictionary, comparer);
        }
    
        /// 
        /// Adds an element with the provided key and value to the .
        /// 
        /// The object to use as the key of the element to add.The object to use as the value of the element to add. is null.An element with the same key already exists in the .The  is read-only.
        public virtual void Add(TKey key, TValue value)
        {
            wrappedDictionary.Add(key, value);
        }
    
        /// 
        /// Determines whether the  contains an element with the specified key.
        /// 
        /// 
        /// true if the  contains an element with the key; otherwise, false.
        /// 
        /// The key to locate in the . is null.
        public virtual bool ContainsKey(TKey key)
        {
            return wrappedDictionary.ContainsKey(key);
        }
    
        /// 
        /// Gets an  containing the keys of the .
        /// 
        /// 
        /// An  containing the keys of the object that implements .
        /// 
        public virtual ICollection Keys
        {
            get
            {
                return wrappedDictionary.Keys;
            }
        }
    
        /// 
        /// Removes the element with the specified key from the .
        /// 
        /// 
        /// true if the element is successfully removed; otherwise, false.  This method also returns false if  was not found in the original .
        /// 
        /// The key of the element to remove. is null.The  is read-only.
        public virtual bool Remove(TKey key)
        {
            return wrappedDictionary.Remove(key);
        }
    
        /// 
        /// Gets the value associated with the specified key.
        /// 
        /// 
        /// true if the object that implements  contains an element with the specified key; otherwise, false.
        /// 
        /// The key whose value to get.When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the  parameter. This parameter is passed uninitialized. is null.
        public virtual bool TryGetValue(TKey key, out TValue value)
        {
            return wrappedDictionary.TryGetValue(key, out value);
        }
    
        /// 
        /// Gets an  containing the values in the .
        /// 
        /// 
        /// An  containing the values in the object that implements .
        /// 
        public virtual ICollection Values
        {
            get
            {
                return wrappedDictionary.Values;
            }
        }
    
        /// 
        /// Gets or sets the element with the specified key.
        /// 
        /// 
        /// The element with the specified key.
        /// 
        /// The key of the element to get or set. is null.The property is retrieved and  is not found.The property is set and the  is read-only.
        public virtual TValue this[TKey key]
        {
            get
            {
                return wrappedDictionary[key];
            }
            set
            {
                wrappedDictionary[key] = value;
            }
        }
    
        /// 
        /// Adds an item to the .
        /// 
        /// The object to add to the .The  is read-only.
        public virtual void Add(KeyValuePair item)
        {
            wrappedDictionary.Add(item);
        }
    
        /// 
        /// Removes all items from the .
        /// 
        /// The  is read-only. 
        public virtual void Clear()
        {
            wrappedDictionary.Clear();
        }
    
        /// 
        /// Determines whether the  contains a specific value.
        /// 
        /// 
        /// true if  is found in the ; otherwise, false.
        /// 
        /// The object to locate in the .
        public virtual bool Contains(KeyValuePair item)
        {
            return wrappedDictionary.Contains(item);
        }
    
        /// 
        /// Copies the elements of the  to an , starting at a particular  index.
        /// 
        /// The one-dimensional  that is the destination of the elements copied from . The  must have zero-based indexing.The zero-based index in  at which copying begins. is null. is less than 0.The number of elements in the source  is greater than the available space from  to the end of the destination .
        public virtual void CopyTo(KeyValuePair[] array, int arrayIndex)
        {
            wrappedDictionary.CopyTo(array, arrayIndex);
        }
    
        /// 
        /// Gets the number of elements contained in the .
        /// 
        /// 
        /// The number of elements contained in the .
        /// 
        public virtual int Count
        {
            get
            {
                return wrappedDictionary.Count;
            }
        }
    
        /// 
        /// Gets a value indicating whether the  is read-only.
        /// 
        /// 
        /// true if the  is read-only; otherwise, false.
        /// 
        public virtual bool IsReadOnly
        {
            get { return wrappedDictionary.IsReadOnly; }
        }
    
        /// 
        /// Removes the first occurrence of a specific object from the .
        /// 
        /// 
        /// true if  was successfully removed from the ; otherwise, false. This method also returns false if  is not found in the original .
        /// 
        /// The object to remove from the .The  is read-only.
        public virtual bool Remove(KeyValuePair item)
        {
            return wrappedDictionary.Remove(item);
        }
    
        /// 
        /// Returns an enumerator that iterates through the collection.
        /// 
        /// 
        /// A  that can be used to iterate through the collection.
        /// 
        /// 1
        public virtual IEnumerator> GetEnumerator()
        {
            return wrappedDictionary.GetEnumerator();
        }
    
        /// 
        /// Returns an enumerator that iterates through a collection.
        /// 
        /// 
        /// An  object that can be used to iterate through the collection.
        /// 
        /// 2
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    

    My use case was to be able to run the same code to manipulate a DataTable and a kendo datasource result which is IDictionary. So, I wrapped the DataTable with my custom IDictionary such that updates to the IDictionary were made on the DataRow. Maybe someone will find that useful and should serve as an example implementation.

    public class DataRowDictionaryWrapper : VirtualDictionary
    {
        private DataRow row;
    
        public DataRowDictionaryWrapper(DataRow row)
        {
            this.row = row;
            this.wrappedDictionary = row.Table.Columns.Cast().ToDictionary(key => key.ColumnName, c => row[c]);
        }
    
        public override void Add(string key, object value)
        {
            DataColumn col = row.Table.Columns[key];
            if (col == null)
            {
                col = new DataColumn(key);
                row.Table.Columns.Add(col);
            }
            row[col] = value;
    
            base[key] = value;
        }
    }
    
    public class DataTableDictionaryWrapper : IEnumerable>
    {
        private DataTable dt;
    
        public DataTableDictionaryWrapper(DataTable dt)
        {
            this.dt = dt;
        }
    
        public IEnumerator> GetEnumerator()
        {
            foreach (DataRow row in dt.Rows)
            {
                yield return new DataRowDictionaryWrapper(row);
            }
        }
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
    

提交回复
热议问题