Igor Kulman

Radenie IEnumerable v C# a Linq

· Igor Kulman

V článku o použití Repository Pattern v ASP.NET som popisoval metódu public static IEnumerable GetList( string sortExpression, int startRowIndex, int maximumRows) na získanie zákazníkov, neuviedol som však jej implementáciu. Ak ovládate jazyk C#, určite vás napadlo, ako parametre startRowIndex a maximumRows využiť. Problém mohol nastať s parametrom sortExpression.

Uvažujme nasledujúcu implementáciu

/// <summary>
 /// Získa zoznam zákazníkov
 /// </summary>
 /// <param name="sortExpression">Stĺpec na triedenie</param>
 /// <param name="startRowIndex">Od záznamu</param>
 /// <param name="maximumRows">Počet záznamov</param>
 /// <returns></returns>
 public static IEnumerable<Customer> GetList(string sortExpression, int startRowIndex, int maximumRows)
 {
 
   return (from c in Db.customers
   where c.UserId == userId
   select new Customer
   {
     AccountNumber = c.AccountNumber,
     BankdId = c.BankId,
     City = c.City,
     Email = c.Email,
     Fax = c.Fax,
     Id = c.Id,
     IdNo = c.IdNo,
     Name = c.Name,
     Phone = c.Phone,
     UserId = c.UserId,
     VatNo = c.VatNo,
     Zip = c.Zip,
     Address = c.Address
   }).Sort(String.IsNullOrEmpty(sortExpression) ? "Id" : sortExpression).Skip(startRowIndex).Take(maximumRows).ToList();
   
 }

Táto metóda vráti zoznam zákazníkov zoradený podľa property objektu Cstomer určenej pomocou sortExpression, prípadne podľa Id. Použitá metóda Sort<T>(this IEnumerable<T> source, string sortExpression) však nie je súčasťou jazyka, je potrebné ju implementovať.

public static class LinqExtensions
{
/// <summary>
 /// Zoradí SQL dopytu pomocou tetxovo zadaného parametra
 /// (z ObjectDataSource sortExpression)
 /// </summary>
 /// <typeparam name="T">Typ</typeparam>
 /// <param name="sortExpression">Výraz podle kterého sa radí</param>
 /// <returns></returns>
 public static IOrderedQueryable<T> Sort<T>(this IEnumerable<T> source, string sortExpression)
 {
 if (String.IsNullOrEmpty(sortExpression))
 {
 // No sorting
 return (IOrderedQueryable<T>)source.AsQueryable<T>();
 }
 
 IQueryable<T> qSource = source.AsQueryable<T>();
 
 bool sortDescending = false;
 if (sortExpression.Contains("DESC"))
 {
 sortDescending = true;
 sortExpression = sortExpression.Replace("DESC", "").Trim();
 }
 
 ParameterExpression param = Expression.Parameter(typeof(T), "item");
 MemberExpression memberExpression = Expression.Property(param, sortExpression);
 
 if (memberExpression.Type == typeof(int))
 {
 Expression<Func<T, int>> sortLambdaExpression = Expression.Lambda<Func<T, int>>
 (Expression.Convert(memberExpression, typeof(int)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 else if (memberExpression.Type == typeof(int?))
 {
 Expression<Func<T, int?>> sortLambdaExpression = Expression.Lambda<Func<T, int?>>
 (Expression.Convert(memberExpression, typeof(int?)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 else if (memberExpression.Type == typeof(bool))
 {
 Expression<Func<T, bool>> sortLambdaExpression = Expression.Lambda<Func<T, bool>>
 (Expression.Convert(memberExpression, typeof(bool)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 else if (memberExpression.Type == typeof(bool?))
 {
 Expression<Func<T, bool?>> sortLambdaExpression = Expression.Lambda<Func<T, bool?>>
 (Expression.Convert(memberExpression, typeof(bool?)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 else if (memberExpression.Type == typeof(float))
 {
 Expression<Func<T, float>> sortLambdaExpression = Expression.Lambda<Func<T, float>>
 (Expression.Convert(memberExpression, typeof(float)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 else if (memberExpression.Type == typeof(float?))
 {
 Expression<Func<T, float?>> sortLambdaExpression = Expression.Lambda<Func<T, float?>>
 (Expression.Convert(memberExpression, typeof(float?)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 else if (memberExpression.Type == typeof(string))
 {
 Expression<Func<T, string>> sortLambdaExpression = Expression.Lambda<Func<T, string>>
 (Expression.Convert(memberExpression, typeof(string)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 else if (memberExpression.Type == typeof(DateTime))
 {
 Expression<Func<T, DateTime>> sortLambdaExpression = Expression.Lambda<Func<T, DateTime>>
 (Expression.Convert(memberExpression, typeof(DateTime)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 else if (memberExpression.Type == typeof(DateTime?))
 {
 Expression<Func<T, DateTime?>> sortLambdaExpression = Expression.Lambda<Func<T, DateTime?>>
 (Expression.Convert(memberExpression, typeof(DateTime?)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 else
 {
 Expression<Func<T, object>> sortLambdaExpression = Expression.Lambda<Func<T, object>>
 (Expression.Convert(memberExpression, typeof(object)), param);
 
 return sortDescending ? qSource.OrderByDescending(sortLambdaExpression) : qSource.OrderBy(sortLambdaExpression);
 }
 }
}
Vďaka tejto triede teraz môžete využívať Repository Patter nazozaj naplno, aj s zoradovaním objektov ľubovoľného typu poďla ľubovoľného parametra.