diff --git a/Source/Euonia.Core/Extensions/Extensions.Collection.cs b/Source/Euonia.Core/Extensions/Extensions.Collection.cs
index f5e21c1..317c05c 100644
--- a/Source/Euonia.Core/Extensions/Extensions.Collection.cs
+++ b/Source/Euonia.Core/Extensions/Extensions.Collection.cs
@@ -5,1078 +5,1072 @@
public static partial class Extensions
{
- private static readonly Random _random = new();
-
- ///
- /// Performs the specified action on each element of the
- ///
- /// The type of the element.
- /// The source.
- /// The System.Action`1 delegate to perform on each element of the .
- /// Throws if is null.
- /// Throws if action is null.
- public static void ForEach(this IEnumerable source, Action action)
- {
- if (source == null)
- {
- throw new NullReferenceException();
- }
-
- if (action == null)
- {
- throw new ArgumentNullException(nameof(action));
- }
-
- foreach (var value in source)
- {
- action(value);
- }
- }
-
- ///
- /// Determines whether the collection contains the object.
- ///
- /// The source.
- /// The value.
- /// The comparison.
- /// true if [contains] [the specified value]; otherwise, false.
- ///
- public static bool Contains(this IEnumerable source, string value, StringComparison comparison)
- {
- if (source == null)
- {
- throw new NullReferenceException();
- }
-
- return source.Any(t => t.Equals(value, comparison));
- }
-
- ///
- /// Determines whether the specified collection [is null or empty].
- ///
- /// The source.
- /// true if the specified source [is null or empty]; otherwise, false.
- public static bool IsNullOrEmpty(this IEnumerable source)
- {
- if (source == null)
- {
- return true;
- }
-
- return !source.GetEnumerator().MoveNext();
- }
-
- ///
- /// Determines whether a sequence is null or empty.
- ///
- ///
- /// A sequence in which to locate a value.
- ///
- public static bool IsNullOrEmpty(this IEnumerable source)
- {
- return source == null || !source.Any();
- }
-
- ///
- /// Determine whether the specified collection is equals to another.
- ///
- /// The type of the collection item.
- /// The source.
- /// The dest.
- /// true if collection is equals to another, false otherwise.
- ///
- /// dest
- public static bool Equals(this IEnumerable source, IEnumerable dest) where T : IComparable
- {
- if (source == null)
- {
- throw new NullReferenceException();
- }
-
- if (dest == null)
- {
- throw new ArgumentNullException(nameof(dest));
- }
-
- return dest.Count() == source.Count() && source.All(dest.Contains);
- }
-
- ///
- /// Concatenates the elements of an object array, using the specified separator between each element.
- ///
- /// Member type.
- /// A collection that contains the objects to concatenate.
- ///
- ///
- public static string Join(this IEnumerable values, string separator)
- {
- if (values == null)
- {
- throw new NullReferenceException();
- }
-
- return string.Join(separator, values);
- }
-
- ///
- /// Concatenates the members of a collection, using the specified separator between each member.
- ///
- /// Member type.
- /// A collection that contains the objects to concatenate.
- /// The string to use as a separator.separator is included in the returned string only if values has more than one element.
- ///
- ///
- ///
- public static string Join(this IEnumerable values, string separator, int startIndex, int count)
- {
- if (values == null)
- {
- throw new NullReferenceException();
- }
-
- if (startIndex >= values.Count())
- {
- throw new IndexOutOfRangeException();
- }
-
- return values.Skip(startIndex).Take(count).Join(separator);
- }
-
- ///
- /// Convert Pageable collection to view collection.
- ///
- ///
- ///
- ///
- public static ViewCollection ToView(this PageableCollection source) where T : class, new()
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- return new ViewCollection(source.ToArray(), source.TotalCount);
- }
-
- ///
- /// Read to a pageable collection.
- ///
- /// The type of the element.
- /// The source.
- /// The total count.
- /// The index.
- /// The size.
- /// A new pageable collection contains all elements of .
- /// Throws if source is null.
- public static PageableCollection Paginate(this IList source, long totalCount, int index, int size)
- {
- if (source == null)
- {
- throw new NullReferenceException();
- }
-
- return new PageableCollection(source) { TotalCount = totalCount, PageNumber = index, PageSize = size };
- }
-
- ///
- /// Converts an exists pageable collection to another.
- ///
- /// The type of collection items.
- /// The source.
- /// The index.
- /// The size.
- /// A new pageable collection.
- /// Throw if source is null.
- public static PageableCollection Convert(this PageableCollection source, int index, int size)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
-
- return new PageableCollection(source) { TotalCount = source.TotalCount, PageNumber = index, PageSize = size };
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public static IEnumerable Shuffle(this IEnumerable enumerable)
- {
- var buffer = enumerable.ToList();
-
- for (var i = 0; i < buffer.Count; i++)
- {
- var j = _random.Next(i, buffer.Count);
-
- yield return buffer[j];
-
- buffer[j] = buffer[i];
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public static ObservableCollection ToObservable(this IEnumerable source)
- {
- var collection = new ObservableCollection(source);
- return collection;
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static IReadOnlyCollection Reify(this IEnumerable source)
- {
- return source switch
- {
- null => throw new ArgumentNullException(nameof(source)),
- IReadOnlyCollection result => result,
- ICollection collection => new CollectionWrapper(collection),
- ICollection nonGenericCollection => new NonGenericCollectionWrapper(nonGenericCollection),
- _ => new List(source)
- };
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void InsertRange(this IList source, int index, IEnumerable items)
- {
- foreach (var item in items)
- {
- source.Insert(index++, item);
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static int FindIndex(this IList source, Predicate selector)
- {
- for (var i = 0; i < source.Count; ++i)
- {
- if (selector(source[i]))
- {
- return i;
- }
- }
-
- return -1;
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public static void AddFirst(this IList source, T item)
- {
- source.Insert(0, item);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public static void AddLast(this IList source, T item)
- {
- source.Insert(source.Count, item);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void InsertAfter(this IList source, T existingItem, T item)
- {
- var index = source.IndexOf(existingItem);
- if (index < 0)
- {
- source.AddFirst(item);
- return;
- }
-
- source.Insert(index + 1, item);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void InsertAfter(this IList source, Predicate selector, T item)
- {
- var index = source.FindIndex(selector);
- if (index < 0)
- {
- source.AddFirst(item);
- return;
- }
-
- source.Insert(index + 1, item);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void InsertBefore(this IList source, T existingItem, T item)
- {
- var index = source.IndexOf(existingItem);
- if (index < 0)
- {
- source.AddLast(item);
- return;
- }
-
- source.Insert(index, item);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void InsertBefore(this IList source, Predicate selector, T item)
- {
- var index = source.FindIndex(selector);
- if (index < 0)
- {
- source.AddLast(item);
- return;
- }
-
- source.Insert(index, item);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void ReplaceWhile(this IList source, Predicate selector, T item)
- {
- for (var i = 0; i < source.Count; i++)
- {
- if (selector(source[i]))
- {
- source[i] = item;
- }
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void ReplaceWhile(this IList source, Predicate selector, Func itemFactory)
- {
- for (var i = 0; i < source.Count; i++)
- {
- var item = source[i];
- if (selector(item))
- {
- source[i] = itemFactory(item);
- }
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void ReplaceOne(this IList source, Predicate selector, T item)
- {
- for (var i = 0; i < source.Count; i++)
- {
- if (selector(source[i]))
- {
- source[i] = item;
- return;
- }
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void ReplaceOne(this IList source, Predicate selector, Func itemFactory)
- {
- for (var i = 0; i < source.Count; i++)
- {
- var item = source[i];
- if (!selector(item))
- {
- continue;
- }
-
- source[i] = itemFactory(item);
- return;
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void ReplaceOne(this IList source, T item, T replaceWith)
- {
- for (var i = 0; i < source.Count; i++)
- {
- if (Comparer.Default.Compare(source[i], item) != 0)
- {
- continue;
- }
-
- source[i] = replaceWith;
- return;
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void MoveItem(this List source, Predicate selector, int targetIndex)
- {
- if (!targetIndex.IsBetween(0, source.Count - 1))
- {
- throw new IndexOutOfRangeException("targetIndex should be between 0 and " + (source.Count - 1));
- }
-
- var currentIndex = source.FindIndex(0, selector);
- if (currentIndex == targetIndex)
- {
- return;
- }
-
- var item = source[currentIndex];
- source.RemoveAt(currentIndex);
- source.Insert(targetIndex, item);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static T GetOrAdd([NotNull] this IList source, Func selector, Func factory)
- {
- Check.EnsureNotNull(source, nameof(source));
-
- var item = source.FirstOrDefault(selector);
-
- if (item == null)
- {
- item = factory();
- source.Add(item);
- }
-
- return item;
- }
-
- ///
- /// Sort a list by a topological sorting, which consider their dependencies.
- ///
- /// The type of the members of values.
- /// A list of objects to sort
- /// Function to resolve the dependencies
- /// Equality comparer for dependencies
- ///
- /// Returns a new list ordered by dependencies.
- /// If A depends on B, then B will come before than A in the resulting list.
- ///
- public static List SortByDependencies(
- this IEnumerable source,
- Func> getDependencies,
- IEqualityComparer comparer = null)
- {
- /* See: http://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp
- * http://en.wikipedia.org/wiki/Topological_sorting
- */
-
- var sorted = new List();
- var visited = new Dictionary(comparer);
-
- foreach (var item in source)
- {
- SortByDependenciesVisit(item, getDependencies, sorted, visited);
- }
-
- return sorted;
- }
-
- ///
- ///
- ///
- /// The type of the members of values.
- /// Item to resolve
- /// Function to resolve the dependencies
- /// List with the sorted items
- /// Dictionary with the visited items
- private static void SortByDependenciesVisit(T item, Func> getDependencies, IList sorted, Dictionary visited)
- {
- var alreadyVisited = visited.TryGetValue(item, out var inProcess);
-
- if (alreadyVisited)
- {
- if (inProcess)
- {
- throw new ArgumentException("Cyclic dependency found! Item: " + item);
- }
- }
- else
- {
- visited[item] = true;
-
- var dependencies = getDependencies(item);
- if (dependencies != null)
- {
- foreach (var dependency in dependencies)
- {
- SortByDependenciesVisit(dependency, getDependencies, sorted, visited);
- }
- }
-
- visited[item] = false;
- sorted.Add(item);
- }
- }
-
- ///
- /// Concatenates the members of a constructed collection of type System.String, using the specified separator between each member.
- /// This is a shortcut for string.Join(...)
- ///
- /// A collection that contains the strings to concatenate.
- /// The string to use as a separator. separator is included in the returned string only if values has more than one element.
- /// A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty.
- public static string JoinAsString(this IEnumerable source, string separator)
- {
- return string.Join(separator, source);
- }
-
- ///
- /// Concatenates the members of a collection, using the specified separator between each member.
- /// This is a shortcut for string.Join(...)
- ///
- /// A collection that contains the objects to concatenate.
- /// The string to use as a separator. separator is included in the returned string only if values has more than one element.
- /// The type of the members of values.
- /// A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty.
- public static string JoinAsString(this IEnumerable source, string separator)
- {
- return string.Join(separator, source);
- }
-
- ///
- /// Filters a by given predicate if given condition is true.
- ///
- /// Enumerable to apply filtering
- /// A boolean value
- /// Predicate to filter the enumerable
- /// Filtered or not filtered enumerable based on
- public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate)
- {
- return condition
- ? source.Where(predicate)
- : source;
- }
-
- ///
- /// Filters a by given predicate if given condition is true.
- ///
- /// Enumerable to apply filtering
- /// A boolean value
- /// Predicate to filter the enumerable
- /// Filtered or not filtered enumerable based on
- public static IEnumerable WhereIf(this IEnumerable source, bool condition, Func predicate)
- {
- return condition
- ? source.Where(predicate)
- : source;
- }
-
- ///
- /// This method is used to try to get a value in a dictionary if it does exists.
- ///
- /// Type of the value
- /// The collection object
- /// Key
- /// Value of the key (or default value if key not exists)
- /// True if key does exists in the dictionary
- internal static bool TryGetValue(this IDictionary dictionary, string key, out T value)
- {
- if (dictionary.TryGetValue(key, out var valueObj) && valueObj is T result)
- {
- value = result;
- return true;
- }
-
- value = default;
- return false;
- }
-
- ///
- /// Gets a value from the dictionary with given key. Returns default value if can not find.
- ///
- /// Dictionary to check and get
- /// Key to find the value
- /// Type of the key
- /// Type of the value
- /// Value if found, default if can not found.
- public static TValue GetOrDefault(this Dictionary dictionary, TKey key)
- {
- return dictionary.TryGetValue(key, out var obj) ? obj : default;
- }
-
- ///
- /// Gets a value from the dictionary with given key. Returns default value if can not find.
- ///
- /// Dictionary to check and get
- /// Key to find the value
- /// Type of the key
- /// Type of the value
- /// Value if found, default if can not found.
- public static TValue GetOrDefault(this IDictionary dictionary, TKey key)
- {
- return dictionary.TryGetValue(key, out var obj) ? obj : default;
- }
-
- ///
- /// Gets a value from the dictionary with given key. Returns default value if can not find.
- ///
- /// Dictionary to check and get
- /// Key to find the value
- /// Type of the key
- /// Type of the value
- /// Value if found, default if can not found.
- public static TValue GetOrDefault(this IReadOnlyDictionary dictionary, TKey key)
- {
- return dictionary.TryGetValue(key, out var obj) ? obj : default;
- }
-
- ///
- /// Gets a value from the dictionary with given key. Returns default value if can not find.
- ///
- /// Dictionary to check and get
- /// Key to find the value
- /// Type of the key
- /// Type of the value
- /// Value if found, default if can not found.
- public static TValue GetOrDefault(this ConcurrentDictionary dictionary, TKey key)
- {
- return dictionary.TryGetValue(key, out var obj) ? obj : default;
- }
-
- ///
- /// Gets a value from the dictionary with given key. Returns default value if can not find.
- ///
- /// Dictionary to check and get
- /// Key to find the value
- /// A factory method used to create the value if not found in the dictionary
- /// Type of the key
- /// Type of the value
- /// Value if found, default if can not found.
- public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory)
- {
- if (dictionary.TryGetValue(key, out var obj))
- {
- return obj;
- }
-
- return dictionary[key] = factory(key);
- }
-
- ///
- /// Gets a value from the dictionary with given key. Returns default value if can not find.
- ///
- /// Dictionary to check and get
- /// Key to find the value
- /// A factory method used to create the value if not found in the dictionary
- /// Type of the key
- /// Type of the value
- /// Value if found, default if can not found.
- public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func factory)
- {
- return dictionary.GetOrAdd(key, _ => factory());
- }
-
- ///
- /// Adds an item to the collection if it's not already in the collection.
- ///
- /// The collection
- /// Item to check and add
- /// Type of the items in the collection
- /// Returns True if added, returns False if not.
- public static bool AddIfNotContains([NotNull] this ICollection source, T item)
- {
- Check.EnsureNotNull(source, nameof(source));
-
- if (source.Contains(item))
- {
- return false;
- }
-
- source.Add(item);
- return true;
- }
-
- ///
- /// Adds items to the collection which are not already in the collection.
- ///
- /// The collection
- /// Item to check and add
- /// Type of the items in the collection
- /// Returns the added items.
- public static IEnumerable AddIfNotContains([NotNull] this ICollection source, IEnumerable items)
- {
- Check.EnsureNotNull(source, nameof(source));
-
- var addedItems = new List();
-
- foreach (var item in items)
- {
- if (source.Contains(item))
- {
- continue;
- }
-
- source.Add(item);
- addedItems.Add(item);
- }
-
- return addedItems;
- }
-
- ///
- /// Adds an item to the collection if it's not already in the collection based on the given .
- ///
- /// The collection
- /// The condition to decide if the item is already in the collection
- /// A factory that returns the item
- /// Type of the items in the collection
- /// Returns True if added, returns False if not.
- public static bool AddIfNotContains([NotNull] this ICollection source, [NotNull] Func predicate, [NotNull] Func itemFactory)
- {
- Check.EnsureNotNull(source, nameof(source));
- Check.EnsureNotNull(predicate, nameof(predicate));
- Check.EnsureNotNull(itemFactory, nameof(itemFactory));
-
- if (source.Any(predicate))
- {
- return false;
- }
-
- source.Add(itemFactory());
- return true;
- }
-
- ///
- /// Removes all items from the collection those satisfy the given .
- ///
- /// Type of the items in the collection
- /// The collection
- /// The condition to remove the items
- /// List of removed items
- public static IList RemoveAll([NotNull] this ICollection source, Func predicate)
- {
- var items = source.Where(predicate).ToList();
-
- foreach (var item in items)
- {
- source.Remove(item);
- }
-
- return items;
- }
-
- ///
- /// Removes all items from the collection those satisfy the given
- /// predicate
- ///
- /// .
- ///
- /// Type of the items in the collection
- /// The collection
- /// Items to be removed from the list
- public static void RemoveAll([NotNull] this ICollection source, IEnumerable items)
- {
- foreach (var item in items)
- {
- source.Remove(item);
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static IDictionary Set(this IDictionary dictionary, TKey key, TValue value)
- {
- dictionary[key] = value;
- return dictionary;
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void TryGetValue(this IDictionary dictionary, TKey key, Action func)
- {
- if (!dictionary.TryGetValue(key, out var value))
- {
- return;
- }
-
- var refValue = (TRef)System.Convert.ChangeType(value, typeof(TRef));
- func(refValue);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void TryGetValue(this IDictionary dictionary, TKey key, Action func)
- {
- if (!dictionary.TryGetValue(key, out var value))
- {
- return;
- }
-
- var refValue = (TRef)value;
- func(refValue);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static void TryGetValue(this IDictionary dictionary, TKey key, Action func)
- {
- if (!dictionary.TryGetValue(key, out var value))
- {
- return;
- }
-
- func(value);
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static TValue GetValue(this IDictionary dictionary, string key, StringComparison comparison)
- {
- var item = dictionary.FirstOrDefault(t => t.Key.Equals(key, comparison));
- return item.Value;
- }
-
- ///
- /// Try get value for specified key from dictionary.
- ///
- /// The key type.
- /// The value type.
- ///
- ///
- ///
- public static TValue TryGetValue(this IDictionary source, TKey key)
- {
- if (source == null)
- {
- throw new NullReferenceException();
- }
-
- return source.TryGetValue(key, out var value) ? value : default;
- }
-
- ///
- /// Try get value for specified key from dictionary.
- ///
- /// The key type.
- /// The value type.
- ///
- ///
- /// The defaut value if key doesn't exists.
- ///
- ///
- public static TValue TryGetValue(this IDictionary source, TKey key, TValue defaultValue)
- {
- if (source == null)
- {
- throw new NullReferenceException();
- }
-
- return source.TryGetValue(key, out var value) ? value : defaultValue;
- }
-
- ///
- /// Try get exists value for specified key or set value if not exists.
- ///
- /// The type of the key.
- /// The type of the value.
- /// The source.
- /// The key.
- /// The value.
- /// Throws if is null.
- public static TValue TryGetOrSetValue(this IDictionary source, TKey key)
- {
- if (source == null)
- {
- throw new NullReferenceException();
- }
-
- if (source.TryGetValue(key, out var value))
- {
- return value;
- }
-
- source.Add(key, value);
- return source[key];
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static TValue TryGetValue(this IDictionary source, string key, TValue defaultValue, StringComparison comparison)
- {
- if (source == null)
- {
- throw new NullReferenceException();
- }
-
- return source.Keys.Contains(key, comparison) ? source.FirstOrDefault(t => t.Key.Equals(key, comparison)).Value : defaultValue;
- }
-
- ///
- /// Gets index of item.
- ///
- ///
- ///
- ///
- ///
- ///
- public static int IndexOf(this IEnumerable enumerable, T item)
- {
- if (enumerable == null)
- throw new ArgumentNullException(nameof(enumerable));
-
- var i = 0;
- foreach (var element in enumerable)
- {
- if (Equals(element, item))
- {
- return i;
- }
-
- i++;
- }
-
- return -1;
- }
-
- ///
- /// Gets index of item which matches the predicate.
- ///
- ///
- ///
- ///
- ///
- public static int IndexOf(this IEnumerable enumerable, Func predicate)
- {
- var i = 0;
- foreach (var element in enumerable)
- {
- if (predicate(element))
- {
- return i;
- }
-
- i++;
- }
-
- return -1;
- }
+ private static readonly Random _random = new();
+
+ ///
+ /// Performs the specified action on each element of the
+ ///
+ /// The type of the element.
+ /// The source.
+ /// The System.Action`1 delegate to perform on each element of the .
+ /// Throws if is null.
+ /// Throws if action is null.
+ public static void ForEach(this IEnumerable source, Action action)
+ {
+ if (source == null)
+ {
+ throw new NullReferenceException();
+ }
+
+ ArgumentAssert.ThrowIfNull(action, nameof(action));
+
+ foreach (var value in source)
+ {
+ action(value);
+ }
+ }
+
+ ///
+ /// Determines whether the collection contains the object.
+ ///
+ /// The source.
+ /// The value.
+ /// The comparison.
+ /// true if [contains] [the specified value]; otherwise, false.
+ ///
+ public static bool Contains(this IEnumerable source, string value, StringComparison comparison)
+ {
+ if (source == null)
+ {
+ throw new NullReferenceException();
+ }
+
+ return source.Any(t => t.Equals(value, comparison));
+ }
+
+ ///
+ /// Determines whether the specified collection [is null or empty].
+ ///
+ /// The source.
+ /// true if the specified source [is null or empty]; otherwise, false.
+ public static bool IsNullOrEmpty(this IEnumerable source)
+ {
+ if (source == null)
+ {
+ return true;
+ }
+
+ return !source.GetEnumerator().MoveNext();
+ }
+
+ ///
+ /// Determines whether a sequence is null or empty.
+ ///
+ ///
+ /// A sequence in which to locate a value.
+ ///
+ public static bool IsNullOrEmpty(this IEnumerable source)
+ {
+ return source == null || !source.Any();
+ }
+
+ ///
+ /// Determine whether the specified collection is equals to another.
+ ///
+ /// The type of the collection item.
+ /// The source.
+ /// The dest.
+ /// true if collection is equals to another, false otherwise.
+ ///
+ /// dest
+ public static bool Equals(this IEnumerable source, IEnumerable dest) where T : IComparable
+ {
+ if (source == null)
+ {
+ throw new NullReferenceException();
+ }
+
+ ArgumentAssert.ThrowIfNull(dest, nameof(dest));
+
+ return dest.Count() == source.Count() && source.All(dest.Contains);
+ }
+
+ ///
+ /// Concatenates the elements of an object array, using the specified separator between each element.
+ ///
+ /// Member type.
+ /// A collection that contains the objects to concatenate.
+ ///
+ ///
+ public static string Join(this IEnumerable values, string separator)
+ {
+ if (values == null)
+ {
+ throw new NullReferenceException();
+ }
+
+ return string.Join(separator, values);
+ }
+
+ ///
+ /// Concatenates the members of a collection, using the specified separator between each member.
+ ///
+ /// Member type.
+ /// A collection that contains the objects to concatenate.
+ /// The string to use as a separator.separator is included in the returned string only if values has more than one element.
+ ///
+ ///
+ ///
+ public static string Join(this IEnumerable values, string separator, int startIndex, int count)
+ {
+ if (values == null)
+ {
+ throw new NullReferenceException();
+ }
+
+ if (startIndex >= values.Count())
+ {
+ throw new IndexOutOfRangeException();
+ }
+
+ return values.Skip(startIndex).Take(count).Join(separator);
+ }
+
+ ///
+ /// Convert Pageable collection to view collection.
+ ///
+ ///
+ ///
+ ///
+ public static ViewCollection ToView(this PageableCollection source) where T : class, new()
+ {
+ if (source == null)
+ {
+ throw new NullReferenceException();
+ }
+
+ return new ViewCollection(source.ToArray(), source.TotalCount);
+ }
+
+ ///
+ /// Read to a pageable collection.
+ ///
+ /// The type of the element.
+ /// The source.
+ /// The total count.
+ /// The index.
+ /// The size.
+ /// A new pageable collection contains all elements of .
+ /// Throws if source is null.
+ public static PageableCollection Paginate(this IList source, long totalCount, int index, int size)
+ {
+ if (source == null)
+ {
+ throw new NullReferenceException();
+ }
+
+ return new PageableCollection(source) { TotalCount = totalCount, PageNumber = index, PageSize = size };
+ }
+
+ ///
+ /// Converts an exists pageable collection to another.
+ ///
+ /// The type of collection items.
+ /// The source.
+ /// The index.
+ /// The size.
+ /// A new pageable collection.
+ /// Throw if source is null.
+ public static PageableCollection Convert(this PageableCollection source, int index, int size)
+ {
+ if (source == null)
+ {
+ throw new NullReferenceException(nameof(source));
+ }
+
+ return new PageableCollection(source) { TotalCount = source.TotalCount, PageNumber = index, PageSize = size };
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IEnumerable Shuffle(this IEnumerable enumerable)
+ {
+ var buffer = enumerable.ToList();
+
+ for (var i = 0; i < buffer.Count; i++)
+ {
+ var j = _random.Next(i, buffer.Count);
+
+ yield return buffer[j];
+
+ buffer[j] = buffer[i];
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static ObservableCollection ToObservable(this IEnumerable source)
+ {
+ var collection = new ObservableCollection(source);
+ return collection;
+ }
+
+ ///
+ /// Reify the specified collection.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IReadOnlyCollection Reify(this IEnumerable source)
+ {
+ return source switch
+ {
+ null => throw new NullReferenceException(),
+ IReadOnlyCollection result => result,
+ ICollection collection => new CollectionWrapper(collection),
+ ICollection nonGenericCollection => new NonGenericCollectionWrapper(nonGenericCollection),
+ _ => new List(source)
+ };
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void InsertRange(this IList source, int index, IEnumerable items)
+ {
+ foreach (var item in items)
+ {
+ source.Insert(index++, item);
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static int FindIndex(this IList source, Predicate selector)
+ {
+ for (var i = 0; i < source.Count; ++i)
+ {
+ if (selector(source[i]))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void AddFirst(this IList source, T item)
+ {
+ source.Insert(0, item);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void AddLast(this IList source, T item)
+ {
+ source.Insert(source.Count, item);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void InsertAfter(this IList source, T existingItem, T item)
+ {
+ var index = source.IndexOf(existingItem);
+ if (index < 0)
+ {
+ source.AddFirst(item);
+ return;
+ }
+
+ source.Insert(index + 1, item);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void InsertAfter(this IList source, Predicate selector, T item)
+ {
+ var index = source.FindIndex(selector);
+ if (index < 0)
+ {
+ source.AddFirst(item);
+ return;
+ }
+
+ source.Insert(index + 1, item);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void InsertBefore(this IList source, T existingItem, T item)
+ {
+ var index = source.IndexOf(existingItem);
+ if (index < 0)
+ {
+ source.AddLast(item);
+ return;
+ }
+
+ source.Insert(index, item);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void InsertBefore(this IList source, Predicate selector, T item)
+ {
+ var index = source.FindIndex(selector);
+ if (index < 0)
+ {
+ source.AddLast(item);
+ return;
+ }
+
+ source.Insert(index, item);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void ReplaceWhile(this IList source, Predicate selector, T item)
+ {
+ for (var i = 0; i < source.Count; i++)
+ {
+ if (selector(source[i]))
+ {
+ source[i] = item;
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void ReplaceWhile(this IList source, Predicate selector, Func itemFactory)
+ {
+ for (var i = 0; i < source.Count; i++)
+ {
+ var item = source[i];
+ if (selector(item))
+ {
+ source[i] = itemFactory(item);
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void ReplaceOne(this IList source, Predicate selector, T item)
+ {
+ for (var i = 0; i < source.Count; i++)
+ {
+ if (selector(source[i]))
+ {
+ source[i] = item;
+ return;
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void ReplaceOne(this IList source, Predicate selector, Func itemFactory)
+ {
+ for (var i = 0; i < source.Count; i++)
+ {
+ var item = source[i];
+ if (!selector(item))
+ {
+ continue;
+ }
+
+ source[i] = itemFactory(item);
+ return;
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void ReplaceOne(this IList source, T item, T replaceWith)
+ {
+ for (var i = 0; i < source.Count; i++)
+ {
+ if (Comparer.Default.Compare(source[i], item) != 0)
+ {
+ continue;
+ }
+
+ source[i] = replaceWith;
+ return;
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void MoveItem(this List source, Predicate selector, int targetIndex)
+ {
+ if (!targetIndex.IsBetween(0, source.Count - 1))
+ {
+ throw new IndexOutOfRangeException("targetIndex should be between 0 and " + (source.Count - 1));
+ }
+
+ var currentIndex = source.FindIndex(0, selector);
+ if (currentIndex == targetIndex)
+ {
+ return;
+ }
+
+ var item = source[currentIndex];
+ source.RemoveAt(currentIndex);
+ source.Insert(targetIndex, item);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static T GetOrAdd([NotNull] this IList source, Func selector, Func factory)
+ {
+ Check.EnsureNotNull(source, nameof(source));
+
+ var item = source.FirstOrDefault(selector);
+
+ if (item == null)
+ {
+ item = factory();
+ source.Add(item);
+ }
+
+ return item;
+ }
+
+ ///
+ /// Sort a list by a topological sorting, which consider their dependencies.
+ ///
+ /// The type of the members of values.
+ /// A list of objects to sort
+ /// Function to resolve the dependencies
+ /// Equality comparer for dependencies
+ ///
+ /// Returns a new list ordered by dependencies.
+ /// If A depends on B, then B will come before than A in the resulting list.
+ ///
+ public static List SortByDependencies(
+ this IEnumerable source,
+ Func