// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Specialized;
using System.Net;
using System.Text;
using Umbraco.Cms.Core;
namespace Umbraco.Extensions;
///
/// Extension methods for Dictionary & ConcurrentDictionary.
///
public static class DictionaryExtensions
{
///
/// Method to Get a value by the key. If the key doesn't exist it will create a new TVal object for the key and return
/// it.
///
///
///
///
///
///
public static TVal GetOrCreate(this IDictionary dict, TKey key)
where TVal : class, new()
{
if (dict.ContainsKey(key) == false)
{
dict.Add(key, new TVal());
}
return dict[key];
}
///
/// 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)
where TKey : notnull
{
while (dict.TryGetValue(key, out TValue? 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 retrieved it, then the item will not be updated
///
public static bool TryUpdateOptimisitic(this ConcurrentDictionary dict, TKey key, Func updateFactory)
where TKey : notnull
{
if (!dict.TryGetValue(key, out TValue? 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)
where TKeyOut : notnull
{
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