C# Extension methods for IEnumerable interface.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using CoreSystem.ValueTypeExtension;

namespace Extensions
{
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
    {
        return enumerable == null || !enumerable.Any();
    }

    /// <summary>
    /// Extension methods for IEnumerable<T> interface
    /// </summary>
    public static class IEnumerableExtension
    {
        /// <summary>
        /// Enumerate each element in the enumeration and execute specified action
        /// </summary>
        /// <typeparam name="T">Type of enumeration</typeparam>
        /// <param name="enumerable">Enumerable collection</param>
        /// <param name="action">Action to perform</param>
        public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
        {
            foreach (T item in enumerable)
                action(item);
        }

        /// <summary>
        /// Read only collection of any enumeration
        /// </summary>
        /// <typeparam name="T">Type of enumeration</typeparam>
        /// <param name="collection">Enumerable collection</param>
        /// <returns>ReadOnlyCollection of the collection</returns>
        public static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> collection)
        {
            return (new List<T>(collection)).AsReadOnly();
        }

        /// <summary>
        /// Converts bytes collection to hexadecimal representation
        /// </summary>
        /// <param name="bytes">Bytes to convert</param>
        /// <returns>Hexadecimal representation string</returns>
        public static string ToHexString(this IEnumerable<byte> bytes)
        {
            return string.Join("", bytes.Select(b => ("0" + b.ToString("X")).Right(2)));
        }

        /// <summary>
        /// Break a list of items into chunks of a specific size.
        /// </summary>
        internal static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, int chunksize)
        {
            if (chunksize <= 0)
            {
                throw new ArgumentException("Argument must be greater than 0", "chunkSize");
            }

            while (source.Any())
            {
                yield return source.Take(chunksize);
                source = source.Skip(chunksize);
            }
        }

        // https://jonlabelle.com/snippets/view/csharp/bulk-insert-generic-list-into-sql-server
        public static DataTable AsDataTable<T>(this IEnumerable<T> data)
        {
            var table = new DataTable();
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));

            foreach (PropertyDescriptor prop in properties)
            {
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
            }

            foreach (T item in data)
            {
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                {
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                }
                table.Rows.Add(row);
            }

            return table;
        }

    }
}