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:
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();
}
}