From 191aaa20cfb141189108ac946b3e67804c64d619 Mon Sep 17 00:00:00 2001 From: ryan Date: Mon, 7 Mar 2022 20:15:38 -0500 Subject: [PATCH] additional collection extensions --- .../Extensions/CollectionExtensions.cs | 124 +++++++++++++++++- 1 file changed, 120 insertions(+), 4 deletions(-) diff --git a/BinaryDad.Extensions/Extensions/CollectionExtensions.cs b/BinaryDad.Extensions/Extensions/CollectionExtensions.cs index 75732e7..d088305 100644 --- a/BinaryDad.Extensions/Extensions/CollectionExtensions.cs +++ b/BinaryDad.Extensions/Extensions/CollectionExtensions.cs @@ -7,11 +7,18 @@ using System.Data; using System.Linq; using System.Linq.Expressions; using System.Reflection; +using System.Web; namespace BinaryDad.Extensions { public static class CollectionExtensions { + /// + /// Adds an item to the , replacing it if it already exists + /// + /// + /// + /// public static void AddReplace(this ICollection items, TItem item, Func matchingProperty) where TItem : class where TProperty : IComparable { var existing = items.FirstOrDefault(i => matchingProperty(i).Equals(matchingProperty(item))); @@ -39,6 +46,21 @@ namespace BinaryDad.Extensions } } + /// + /// Groups a set of items into batches of a given batch size + /// + /// + /// + /// + /// + public static IEnumerable> Batch(this IEnumerable items, int batchSize) + { + return items.Select((Item, Index) => new { Item, Index }) + .GroupBy(x => x.Index / batchSize) + .Select(x => x.Select(t => t.Item).ToList()) + .ToList(); + } + /// /// Returns a distinct list of elements using the first-matched item on a specific property /// @@ -69,6 +91,16 @@ namespace BinaryDad.Extensions #region ToDataTable + /// + /// Converts a typed collection into a . This method excludes the column if is bound to a property. + /// + /// + /// + /// Specifies whether the data column should use the name from , if bound to a property. + /// + /// + public static DataTable ToDataTable(this IEnumerable collection, bool useColumnAttributeName = false, string tableName = null) => ToDataTable(collection, null, useColumnAttributeName, tableName); + /// /// Converts a typed collection into a . This method excludes the column if is bound to a property. /// @@ -78,7 +110,19 @@ namespace BinaryDad.Extensions /// Specifies whether the data column should use the name from , if bound to a property. /// /// - public static DataTable ToDataTable(this IEnumerable collection, Func columnNameModifier, bool useColumnAttributeName = false, string tableName = null) + public static DataTable ToDataTable(this IEnumerable collection, Func columnNameModifier, bool useColumnAttributeName = false, string tableName = null) => ToDataTable(collection, columnNameModifier, null, useColumnAttributeName, tableName); + + /// + /// Converts a typed collection into a . This method excludes the column if is bound to a property. + /// + /// + /// + /// If a non-null string is returned, the column name is overridden + /// If a condition is supplied, only columns matching the condition will be included + /// Specifies whether the data column should use the name from , if bound to a property. + /// + /// + public static DataTable ToDataTable(this IEnumerable collection, Func columnNameModifier, Func columnIncludeModifier, bool useColumnAttributeName = false, string tableName = null) { if (collection == null) { @@ -116,10 +160,25 @@ namespace BinaryDad.Extensions var propertyInfo = type .GetProperties() - .Where(p => !p.HasCustomAttribute()) + .Where(p => + { + // automatically ignore [NotMapped] attribute properties + if (p.HasCustomAttribute()) + { + return false; + } + + // allow for custom column inclusion + if (columnIncludeModifier != null) + { + return columnIncludeModifier.Invoke(p); + } + + return true; + }) .Select(p => { - string columnName = p.Name; + var columnName = p.Name; string columnTypeName = null; // set column name to be either the property name @@ -206,6 +265,13 @@ namespace BinaryDad.Extensions #region Join + /// + /// Serializes a collection of objects (wrapper for ) + /// + /// + /// + /// + /// public static string Join(this IEnumerable items, string separator = "") where T : IComparable { if (items == null) @@ -221,6 +287,15 @@ namespace BinaryDad.Extensions return string.Join(separator, items.ToArray()); } + /// + /// Serializes a collection of objects with a custom property selector (wrapper for ) + /// + /// + /// + /// + /// + /// + /// public static string Join(this IEnumerable items, Func selector, string separator = "") where TSelector : IComparable => Join(items.Select(selector), separator); /// @@ -537,7 +612,48 @@ namespace BinaryDad.Extensions } } - public static Dictionary ToDictionary(this IEnumerable> source, IEqualityComparer comparer = null) => source.ToDictionary(k => k.Key, v => v.Value, comparer); + public static Dictionary ToDictionary(this IEnumerable> source) => source.ToDictionary(k => k.Key, v => v.Value); + + public static Dictionary ToDictionary(this IEnumerable> source, IEqualityComparer comparer) => source.ToDictionary(k => k.Key, v => v.Value, comparer); + + public static void Add(this IDictionary source, KeyValuePair value) => source.Add(value.Key, value.Value); + + public static T To(this IDictionary source) where T : class, new() + { + var instance = new T(); + + var properties = typeof(T).GetProperties(); + + foreach (var property in properties) + { + var propertyName = property.Name; + + if (source.ContainsKey(propertyName)) + { + property.SetValue(instance, source[propertyName]); + } + } + + return instance; + } + + /// + /// Creates a query string using a dictionary + /// + /// + /// + public static string ToQueryString(this IEnumerable> source) where T : IConvertible + { + // allows us to get a HttpValueCollection which provides proper serialiation/encoding + var collection = HttpUtility.ParseQueryString(string.Empty); + + foreach (var pair in source) + { + collection.Add(pair.Key, pair.Value?.ToString()); + } + + return collection.ToString(); + } #region Replace