// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschränkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; namespace Squidex.Infrastructure { public static class CollectionExtensions { public static ImmutableDictionary SetItem(this ImmutableDictionary dictionary, TKey key, Func updater) { if (dictionary.TryGetValue(key, out var value)) { var newValue = updater(value); if (!Equals(newValue, value)) { return dictionary.SetItem(key, newValue); } } return dictionary; } public static bool TryGetValue(this IReadOnlyDictionary values, TKey key, out TBase item) where TValue : TBase { if (values.TryGetValue(key, out var value)) { item = value; return true; } else { item = default(TBase); return false; } } public static IEnumerable OrEmpty(this IEnumerable source) { return source ?? Enumerable.Empty(); } public static IEnumerable Concat(this IEnumerable source, T value) { return source.Concat(Enumerable.Repeat(value, 1)); } public static int SequentialHashCode(this IEnumerable collection) { return collection.SequentialHashCode(EqualityComparer.Default); } public static int SequentialHashCode(this IEnumerable collection, IEqualityComparer comparer) { var hashCode = 17; foreach (var item in collection) { if (!Equals(item, null)) { hashCode = (hashCode * 23) + comparer.GetHashCode(item); } } return hashCode; } public static int OrderedHashCode(this IEnumerable collection) { return collection.OrderedHashCode(EqualityComparer.Default); } public static int OrderedHashCode(this IEnumerable collection, IEqualityComparer comparer) { Guard.NotNull(comparer, nameof(comparer)); var hashCodes = collection.Where(x => !Equals(x, null)).Select(x => x.GetHashCode()).OrderBy(x => x).ToArray(); var hashCode = 17; foreach (var code in hashCodes) { hashCode = (hashCode * 23) + code; } return hashCode; } public static int DictionaryHashCode(this IDictionary dictionary) { return DictionaryHashCode(dictionary, EqualityComparer.Default, EqualityComparer.Default); } public static int DictionaryHashCode(this IDictionary dictionary, IEqualityComparer keyComparer, IEqualityComparer valueComparer) { var hashCode = 17; foreach (var kvp in dictionary.OrderBy(x => x.Key)) { hashCode = (hashCode * 23) + keyComparer.GetHashCode(kvp.Key); if (!Equals(kvp.Value, null)) { hashCode = (hashCode * 23) + valueComparer.GetHashCode(kvp.Value); } } return hashCode; } public static bool EqualsDictionary(this IReadOnlyDictionary dictionary, IReadOnlyDictionary other) { return EqualsDictionary(dictionary, other, EqualityComparer.Default, EqualityComparer.Default); } public static bool EqualsDictionary(this IReadOnlyDictionary dictionary, IReadOnlyDictionary other, IEqualityComparer keyComparer, IEqualityComparer valueComparer) { var comparer = new KeyValuePairComparer(keyComparer, valueComparer); return other != null && dictionary.Count == other.Count && !dictionary.Except(other, comparer).Any(); } public static TValue GetOrDefault(this IReadOnlyDictionary dictionary, TKey key) { return dictionary.GetOrCreate(key, _ => default(TValue)); } public static TValue GetOrAddDefault(this IDictionary dictionary, TKey key) { return dictionary.GetOrAdd(key, _ => default(TValue)); } public static TValue GetOrNew(this IReadOnlyDictionary dictionary, TKey key) where TValue : class, new() { return dictionary.GetOrCreate(key, _ => new TValue()); } public static TValue GetOrAddNew(this IDictionary dictionary, TKey key) where TValue : class, new() { return dictionary.GetOrAdd(key, _ => new TValue()); } public static TValue GetOrCreate(this IReadOnlyDictionary dictionary, TKey key, Func creator) { if (!dictionary.TryGetValue(key, out var result)) { result = creator(key); } return result; } public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func creator) { if (!dictionary.TryGetValue(key, out var result)) { result = creator(key); dictionary.Add(key, result); } return result; } public static void Foreach(this IEnumerable collection, Action action) { foreach (var item in collection) { action(item); } } public sealed class KeyValuePairComparer : IEqualityComparer> { private readonly IEqualityComparer keyComparer; private readonly IEqualityComparer valueComparer; public KeyValuePairComparer(IEqualityComparer keyComparer, IEqualityComparer valueComparer) { this.keyComparer = keyComparer; this.valueComparer = valueComparer; } public bool Equals(KeyValuePair x, KeyValuePair y) { return keyComparer.Equals(x.Key, y.Key) && valueComparer.Equals(x.Value, y.Value); } public int GetHashCode(KeyValuePair obj) { return keyComparer.GetHashCode(obj.Key) ^ valueComparer.GetHashCode(obj.Value); } } } }