extensions
Linq Extensions
Here is my class of linq extensions I use.
This is an example of using the extension in a unit test.
[TestMethod] public void Linq_OrderBy() { List<User> userList = UserList.OrderBy( "FirstName" ).ToList(); Trace.WriteLine( "=== Order By FirstName ascending ===" ); foreach ( User user in userList ) Trace.WriteLine( $"FirstName: {user.FirstName}, LastName: {user.LastName}" ); userList = UserList.OrderBy( "LastName", false ).ToList(); Trace.WriteLine( "=== Order By LastName descending ====" ); foreach ( User user in userList ) Trace.WriteLine( $"FirstName: {user.FirstName}, LastName: {user.LastName}" ); } private static readonly List<User> UserList = new List<User>() { new User { FirstName = "firstName03", LastName= "lastName08" }, new User { FirstName = "firstName07", LastName= "lastName04" }, new User { FirstName = "firstName06", LastName= "lastName05" }, new User { FirstName = "firstName04", LastName= "lastName07" }, new User { FirstName = "firstName10", LastName= "lastName01" }, new User { FirstName = "firstName09", LastName= "lastName02" }, new User { FirstName = "firstName08", LastName= "lastName03" }, new User { FirstName = "firstName05", LastName= "lastName06" }, new User { FirstName = "firstName02", LastName= "lastName09" }, new User { FirstName = "firstName01", LastName= "lastName10" } };
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace Dahl.Core.Extensions { public static partial class Extensions { //----------------------------------------------------------------------------------------- /// <summary> /// Sorts the elements of a sequence according to a key. /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="source"></param> /// <param name="keySelector"></param> /// <param name="descending"></param> /// <returns></returns> public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, bool descending ) { if ( descending ) return source.OrderByDescending( keySelector ); return source.OrderBy( keySelector ); } //----------------------------------------------------------------------------------------- /// <summary> /// /// </summary> /// <typeparam name="TSource"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="source"></param> /// <param name="keySelector"></param> /// <param name="descending"></param> /// <returns></returns> public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>( this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, bool descending ) { return descending ? source.OrderByDescending( keySelector ) : source.OrderBy( keySelector ); } //----------------------------------------------------------------------------------------- /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="list"></param> /// <param name="sortExpression"></param> /// <param name="sortAscending"></param> /// <returns></returns> public static IQueryable<T> OrderBy<T>( this IQueryable<T> list, string sortExpression, bool sortAscending = true ) { return sortAscending ? list.OrderBy( f => OrderFunc( f, sortExpression ) ) : list.OrderByDescending( f => OrderFunc( f, sortExpression ) ); } //----------------------------------------------------------------------------------------- /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="list"></param> /// <param name="sortExpression"></param> /// <param name="sortAscending"></param> /// <returns></returns> public static IEnumerable<T> OrderBy<T>( this IEnumerable<T> list, string sortExpression, bool sortAscending = true ) { return sortAscending ? list.OrderBy( f => OrderFunc( f, sortExpression ) ) : list.OrderByDescending( f => OrderFunc( f, sortExpression ) ); } //----------------------------------------------------------------------------------------- /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <param name="propertyName"></param> /// <returns></returns> public static object GetChildObject<T>( T obj, string propertyName ) { Type t = obj.GetType(); PropertyInfo prop = t.GetProperty( propertyName ); if ( prop == null ) { string msg = $"PropertyName \"{propertyName}\" is not defined in class \"{obj.GetType().FullName}\"."; throw new ArgumentException( msg ); } return prop.GetValue( obj, null ) ?? Activator.CreateInstance( prop.PropertyType ); } //----------------------------------------------------------------------------------------- /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <param name="propertyName"></param> /// <returns></returns> private static object OrderFunc<T>( T obj, string propertyName ) { string propName = propertyName; object newObj = obj; if ( propertyName.Contains( '.' ) ) { // the requested property is contained in a child object string[] parts = propertyName.Split( '.' ); int numParts = parts.Length - 1; for ( int i = 0; i < numParts; i++ ) newObj = GetChildObject( newObj, parts[i] ); propName = parts[numParts]; } PropertyInfo propertyGetter = newObj.GetType() .GetProperty( propName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase ); if ( propertyGetter == null ) { string msg = @"Sort Expression could not find property name provided<br />" + $"PropertyName: {propertyName}"; throw new ArgumentException( msg ); } return propertyGetter.GetValue( newObj, null ); } //----------------------------------------------------------------------------------------- /// <summary> /// /// </summary> /// <typeparam name="TSrc"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="src"></param> /// <param name="selector"></param> /// <returns></returns> public static IEnumerable<TSrc> DistinctBy<TSrc, TKey>( this IEnumerable<TSrc> src, Func<TSrc, TKey> selector ) { HashSet<TKey> keys = new HashSet<TKey>(); return src.Where( element => keys.Add( selector( element ) ) ); } } }