1: /// <summary>
2: /// Provides extention methods to the dictionary class
3: /// </summary>
4: public static class DictionaryExtensions
5: {
6: /// <summary>
7: /// Creates a new Dictionary with the key and value of the current dictionary reversed.
8: /// This method should be not used when duplicate values are expected because collisions will occur.
9: /// </summary>
10: /// <typeparam name="K">The Key type</typeparam>
11: /// <typeparam name="V">The Value type</typeparam>
12: /// <param name="dictionary">The dictionary to use</param>
13: /// <returns>A Dictionary with the keys and values of the current dictionary reversed</returns>
14: public static Dictionary<V, K> CreateDictionaryOfValueAndKey<K, V>(this Dictionary<K, V> dictionary)
15: {
16: Dictionary<V, K> result = new Dictionary<V,K>();
17: foreach (KeyValuePair<K, V> keyValuePair in dictionary)
18: {
19: result.Add(keyValuePair.Value, keyValuePair.Key);
20: }
21:
22: return result;
23: }
24:
25: /// <summary>
26: /// Creates a new MultiDictionary with the key and value of the current dictionary reversed.
27: /// This method should be used when duplicate values are expected.
28: /// </summary>
29: /// <typeparam name="K">The Key type</typeparam>
30: /// <typeparam name="V">The Value type</typeparam>
31: /// <param name="dictionary">The dictionary to use</param>
32: /// <returns>A MultiDictionary with the keys and values of the current dictionary reversed</returns>
33: public static MultiDictionary<V, K> CreateMultiDictionaryOfValueAndKey<K, V>(this Dictionary<K, V> dictionary)
34: {
35: MultiDictionary<V, K> result = new MultiDictionary<V, K>();
36: foreach (KeyValuePair<K, V> keyValuePair in dictionary)
37: {
38: result.Add(keyValuePair.Value, keyValuePair.Key);
39: }
40:
41: return result;
42: }
43:
44: /// <summary>
45: /// Merges the targetDictionary with the sourceDictionary, deleting items that arent in sourceDictionary,
46: /// adding items that are in sourceDictionary but not in the targetDictionary, and updating items that are in both,
47: /// setting them to the value in sourceDictionary
48: /// </summary>
49: /// <typeparam name="K">The Key type</typeparam>
50: /// <typeparam name="V">The Value type of the source and target dictionaries</typeparam>
51: /// <param name="targetDictionary">The current dictionary to merge entries into</param>
52: /// <param name="sourceDictionary">The new dictionary with the most recent data</param>
53: public static void Merge<K, V>(
54: this Dictionary<K, V> targetDictionary,
55: Dictionary<K, V> sourceDictionary)
56: {
57: Merge(targetDictionary, sourceDictionary, null, null, null, null, null);
58: }
59:
60: /// <summary>
61: /// Merges the targetDictionary with the sourceDictionary, deleting items that arent in sourceDictionary,
62: /// adding items that are in sourceDictionary but not in the targetDictionary, and updating items that are in both,
63: /// setting them to the value in sourceDictionary
64: /// </summary>
65: /// <typeparam name="K">The Key type</typeparam>
66: /// <typeparam name="VTarget">The Value type of the target dictionary</typeparam>
67: /// <typeparam name="VSource">The Value type of the source dictionary</typeparam>
68: /// <param name="targetDictionary">The current dictionary to merge entries into</param>
69: /// <param name="sourceDictionary">The new dictionary with the most recent data</param>
70: public static void Merge<K, VTarget, VSource>(
71: this Dictionary<K, VTarget> targetDictionary,
72: Dictionary<K, VSource> sourceDictionary)
73: {
74: Merge(targetDictionary, sourceDictionary, null, null, null, null, null);
75: }
76:
77: /// <summary>
78: /// Merges the targetDictionary with the sourceDictionary, deleting items that arent in sourceDictionary,
79: /// adding items that are in sourceDictionary but not in the targetDictionary, and updating items that are in both,
80: /// setting them to the value in sourceDictionary
81: /// </summary>
82: /// <typeparam name="K">The Key type</typeparam>
83: /// <typeparam name="V">The Value type of the source and target dictionaries</typeparam>
84: /// <param name="targetDictionary">The current dictionary to merge entries into</param>
85: /// <param name="sourceDictionary">The new dictionary with the most recent data</param>
86: /// <param name="valueUpdater">The action to use to update values that share the same key</param>
87: public static void Merge<K, V>(
88: this Dictionary<K, V> targetDictionary,
89: Dictionary<K, V> sourceDictionary,
90: Func<V, V, bool> valueUpdater)
91: {
92: Func<V, V> valueMapper = x => x;
93: Merge(targetDictionary, sourceDictionary, valueMapper, valueUpdater, null, null, null);
94: }
95:
96: /// <summary>
97: /// Merges the targetDictionary with the sourceDictionary, deleting items that arent in sourceDictionary,
98: /// adding items that are in sourceDictionary but not in the targetDictionary, and updating items that are in both,
99: /// setting them to the value in sourceDictionary
100: /// </summary>
101: /// <typeparam name="K">The Key type</typeparam>
102: /// <typeparam name="VTarget">The Value type of the target dictionary</typeparam>
103: /// <typeparam name="VSource">The Value type of the source dictionary</typeparam>
104: /// <param name="targetDictionary">The current dictionary to merge entries into</param>
105: /// <param name="sourceDictionary">The new dictionary with the most recent data</param>
106: /// <param name="valueMapper">The transform to convert VSource to VTarget</param>
107: /// <param name="valueUpdater">The action to use to update values that share the same key</param>
108: public static void Merge<K, VTarget, VSource>(
109: this Dictionary<K, VTarget> targetDictionary,
110: Dictionary<K, VSource> sourceDictionary,
111: Func<VSource, VTarget> valueMapper,
112: Func<VTarget, VTarget, bool> valueUpdater)
113: {
114: Merge(targetDictionary, sourceDictionary, valueMapper, valueUpdater, null, null, null);
115: }
116:
117: /// <summary>
118: /// Merges the targetDictionary with the sourceDictionary, deleting items that arent in sourceDictionary,
119: /// adding items that are in sourceDictionary but not in the targetDictionary, and updating items that are in both,
120: /// setting them to the value in sourceDictionary
121: /// </summary>
122: /// <typeparam name="K">The Key type</typeparam>
123: /// <typeparam name="V">The Value type of the source and target dictionaries</typeparam>
124: /// <param name="targetDictionary">The current dictionary to merge entries into</param>
125: /// <param name="sourceDictionary">The new dictionary with the most recent data</param>
126: /// <param name="itemAddedEventHandler">The event to fire for items that were added</param>
127: /// <param name="itemChangedEventHandler">The event to fire for items that were changed</param>
128: /// <param name="itemDeletedEventHandler">The event to fire for items that were deleted</param>
129: public static void Merge<K, V>(
130: this Dictionary<K, V> targetDictionary,
131: Dictionary<K, V> sourceDictionary,
132: EventHandler<DictionaryItemAddedEventArgs<K, V>> itemAddedEventHandler,
133: EventHandler<DictionaryItemChangedEventArgs<K, V>> itemChangedEventHandler,
134: EventHandler<DictionaryItemDeletedEventArgs<K, V>> itemDeletedEventHandler)
135: {
136: Func<V, V> valueMapper = x => x;
137: Merge(targetDictionary, sourceDictionary, valueMapper, null, itemAddedEventHandler, itemChangedEventHandler, itemDeletedEventHandler);
138: }
139:
140: /// <summary>
141: /// Merges the targetDictionary with the sourceDictionary, deleting items that arent in sourceDictionary,
142: /// adding items that are in sourceDictionary but not in the targetDictionary, and updating items that are in both,
143: /// setting them to the value in sourceDictionary
144: /// </summary>
145: /// <typeparam name="K">The Key type</typeparam>
146: /// <typeparam name="VTarget">The Value type of the target dictionary</typeparam>
147: /// <typeparam name="VSource">The Value type of the source dictionary</typeparam>
148: /// <param name="targetDictionary">The current dictionary to merge entries into</param>
149: /// <param name="sourceDictionary">The new dictionary with the most recent data</param>
150: /// <param name="valueMapper">The transform to convert VSource to VTarget</param>
151: /// <param name="itemAddedEventHandler">The event to fire for items that were added</param>
152: /// <param name="itemChangedEventHandler">The event to fire for items that were changed</param>
153: /// <param name="itemDeletedEventHandler">The event to fire for items that were deleted</param>
154: public static void Merge<K, VTarget, VSource>(
155: this Dictionary<K, VTarget> targetDictionary,
156: Dictionary<K, VSource> sourceDictionary,
157: Func<VSource, VTarget> valueMapper,
158: EventHandler<DictionaryItemAddedEventArgs<K, VTarget>> itemAddedEventHandler,
159: EventHandler<DictionaryItemChangedEventArgs<K, VTarget>> itemChangedEventHandler,
160: EventHandler<DictionaryItemDeletedEventArgs<K, VTarget>> itemDeletedEventHandler)
161: {
162: Merge(targetDictionary, sourceDictionary, valueMapper, null, itemAddedEventHandler, itemChangedEventHandler, itemDeletedEventHandler);
163: }
164:
165: /// <summary>
166: /// Merges the targetDictionary with the sourceDictionary, deleting items that arent in sourceDictionary,
167: /// adding items that are in sourceDictionary but not in the targetDictionary, and updating items that are in both,
168: /// setting them to the value in sourceDictionary
169: /// </summary>
170: /// <typeparam name="K">The Key type</typeparam>
171: /// <typeparam name="VTarget">The Value type of the target dictionary</typeparam>
172: /// <typeparam name="VSource">The Value type of the source dictionary</typeparam>
173: /// <param name="targetDictionary">The current dictionary to merge entries into</param>
174: /// <param name="sourceDictionary">The new dictionary with the most recent data</param>
175: /// <param name="valueMapper">The transform to convert VSource to VTarget</param>
176: /// <param name="valueUpdater">The action to use to update values that share the same key</param>
177: /// <param name="itemAddedEventHandler">The event to fire for items that were added</param>
178: /// <param name="itemChangedEventHandler">The event to fire for items that were changed</param>
179: /// <param name="itemDeletedEventHandler">The event to fire for items that were deleted</param>
180: public static void Merge<K, VTarget, VSource>(
181: this Dictionary<K, VTarget> targetDictionary,
182: Dictionary<K, VSource> sourceDictionary,
183: Func<VSource, VTarget> valueMapper,
184: Func<VTarget, VTarget, bool> valueUpdater,
185: EventHandler<DictionaryItemAddedEventArgs<K, VTarget>> itemAddedEventHandler,
186: EventHandler<DictionaryItemChangedEventArgs<K, VTarget>> itemChangedEventHandler,
187: EventHandler<DictionaryItemDeletedEventArgs<K, VTarget>> itemDeletedEventHandler)
188: {
189: foreach (var keyValuePair in sourceDictionary)
190: {
191: VTarget newValue = valueMapper(keyValuePair.Value);
192:
193: VTarget oldValue;
194: if (targetDictionary.TryGetValue(keyValuePair.Key, out oldValue))
195: {
196: bool changed = true;
197: if (valueUpdater == null)
198: {
199: targetDictionary[keyValuePair.Key] = newValue;
200: }
201: else
202: {
203: changed = valueUpdater(oldValue, newValue);
204: }
205:
206: if (itemChangedEventHandler != null && changed)
207: {
208: itemChangedEventHandler(targetDictionary, new DictionaryItemChangedEventArgs<K, VTarget>(keyValuePair.Key, oldValue, newValue));
209: }
210: }
211: else
212: {
213: targetDictionary.Add(keyValuePair.Key, newValue);
214: if (itemAddedEventHandler != null)
215: {
216: itemAddedEventHandler(targetDictionary, new DictionaryItemAddedEventArgs<K, VTarget>(keyValuePair.Key, newValue));
217: }
218: }
219: }
220:
221: List<KeyValuePair<K, VTarget>> itemsToDelete = new List<KeyValuePair<K, VTarget>>();
222: foreach (var keyValuePair in targetDictionary)
223: {
224: if (!sourceDictionary.ContainsKey(keyValuePair.Key))
225: {
226: itemsToDelete.Add(keyValuePair);
227: }
228: }
229:
230: foreach (var keyValuePair in itemsToDelete)
231: {
232: targetDictionary.Remove(keyValuePair.Key);
233: if (itemDeletedEventHandler != null)
234: {
235: itemDeletedEventHandler(targetDictionary, new DictionaryItemDeletedEventArgs<K, VTarget>(keyValuePair.Key, keyValuePair.Value));
236: }
237: }
238: }
239: }