using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Text; using System.Web.Mvc; using System.Web; namespace Umbraco.Core { /// /// Extension methods for dictionary & concurrentdictionary /// internal static class DictionaryExtensions { /// /// Updates an item with the specified key with the specified value /// /// /// /// /// /// /// /// /// Taken from: http://stackoverflow.com/questions/12240219/is-there-a-way-to-use-concurrentdictionary-tryupdate-with-a-lambda-expression /// /// If there is an item in the dictionary with the key, it will keep trying to update it until it can /// public static bool TryUpdate(this ConcurrentDictionary dict, TKey key, Func updateFactory) { TValue curValue; while (dict.TryGetValue(key, out curValue)) { if (dict.TryUpdate(key, updateFactory(curValue), curValue)) return true; //if we're looping either the key was removed by another thread, or another thread //changed the value, so we start again. } return false; } /// /// Updates an item with the specified key with the specified value /// /// /// /// /// /// /// /// /// Taken from: http://stackoverflow.com/questions/12240219/is-there-a-way-to-use-concurrentdictionary-tryupdate-with-a-lambda-expression /// /// WARNING: If the value changes after we've retreived it, then the item will not be updated /// public static bool TryUpdateOptimisitic(this ConcurrentDictionary dict, TKey key, Func updateFactory) { TValue curValue; if (!dict.TryGetValue(key, out curValue)) return false; dict.TryUpdate(key, updateFactory(curValue), curValue); return true;//note we return true whether we succeed or not, see explanation below. } /// /// Converts a dictionary to another type by only using direct casting /// /// /// /// /// public static IDictionary ConvertTo(this IDictionary d) { var result = new Dictionary(); foreach (DictionaryEntry v in d) { result.Add((TKeyOut)v.Key, (TValOut)v.Value); } return result; } /// /// Converts a dictionary to another type using the specified converters /// /// /// /// /// /// /// public static IDictionary ConvertTo(this IDictionary d, Func keyConverter, Func valConverter) { var result = new Dictionary(); foreach (DictionaryEntry v in d) { result.Add(keyConverter(v.Key), valConverter(v.Value)); } return result; } /// /// Converts a dictionary to a NameValueCollection /// /// /// public static NameValueCollection ToNameValueCollection(this IDictionary d) { var n = new NameValueCollection(); foreach (var i in d) { n.Add(i.Key, i.Value); } return n; } /// /// Converts a dictionary to a FormCollection /// /// /// public static FormCollection ToFormCollection(this IDictionary d) { var n = new FormCollection(); foreach (var i in d) { n.Add(i.Key, Convert.ToString(i.Value)); } return n; } /// /// Returns a new dictionary of this ... others merged leftward. /// /// /// /// /// /// /// /// /// Reference: http://stackoverflow.com/questions/294138/merging-dictionaries-in-c /// public static T MergeLeft(this T me, params IDictionary[] others) where T : IDictionary, new() { var newMap = new T(); foreach (var p in (new List> { me }).Concat(others).SelectMany(src => src)) { newMap[p.Key] = p.Value; } return newMap; } /// /// Returns the value of the key value based on the key, if the key is not found, a null value is returned /// /// The type of the key. /// The type of the val. /// The d. /// The key. /// The default value. /// public static TVal GetValue(this IDictionary d, TKey key, TVal defaultValue = default(TVal)) { if (d.ContainsKey(key)) { return d[key]; } return defaultValue; } /// /// Returns the value of the key value based on the key as it's string value, if the key is not found, then an empty string is returned /// /// /// /// public static string GetValueAsString(this IDictionary d, TKey key) { if (d.ContainsKey(key)) { return d[key].ToString(); } return String.Empty; } /// /// Returns the value of the key value based on the key as it's string value, if the key is not found or is an empty string, then the provided default value is returned /// /// /// /// /// public static string GetValueAsString(this IDictionary d, TKey key, string defaultValue) { if (d.ContainsKey(key)) { var value = d[key].ToString(); if (value != string.Empty) return value; } return defaultValue; } /// contains key ignore case. /// The dictionary. /// The key. /// Value Type /// The contains key ignore case. public static bool ContainsKeyIgnoreCase(this IDictionary dictionary, string key) { return dictionary.Keys.Any(i => i.Equals(key, StringComparison.CurrentCultureIgnoreCase)); } /// /// Converts a dictionary object to a query string representation such as: /// firstname=shannon&lastname=deminick /// /// /// public static string ToQueryString(this IDictionary d) { if (!d.Any()) return ""; var builder = new StringBuilder(); foreach (var i in d) { builder.Append(String.Format("{0}={1}&", HttpUtility.UrlEncode(i.Key), i.Value == null ? string.Empty : HttpUtility.UrlEncode(i.Value.ToString()))); } return builder.ToString().TrimEnd('&'); } /// The get entry ignore case. /// The dictionary. /// The key. /// The type /// The entry public static TValue GetEntryIgnoreCase(this IDictionary dictionary, string key) { return dictionary.GetEntryIgnoreCase(key, default(TValue)); } /// The get entry ignore case. /// The dictionary. /// The key. /// The default value. /// The type /// The entry public static TValue GetEntryIgnoreCase(this IDictionary dictionary, string key, TValue defaultValue) { key = dictionary.Keys.Where(i => i.Equals(key, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault(); return !key.IsNullOrWhiteSpace() ? dictionary[key] : defaultValue; } } }