File: System\Data\EnumerableRowCollectionExtensions.cs
Project: ndp\fx\src\DataSet\System.Data.DataSetExtensions.csproj (System.Data.DataSetExtensions)
//------------------------------------------------------------------------------
// <copyright file="EnumRowCollectionExtensions.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
// <owner current="true" primary="false">Microsoft</owner>
//------------------------------------------------------------------------------
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Globalization;
using System.Diagnostics;
 
namespace System.Data
{
    /// <summary>
    /// This static class defines the extension methods that add LINQ operator functionality
    /// within IEnumerableDT and IOrderedEnumerableDT.
    /// </summary>
    public static class EnumerableRowCollectionExtensions
    {
        /// <summary>
        /// LINQ's Where operator for generic EnumerableRowCollection.
        /// </summary>
        public static EnumerableRowCollection<TRow> Where<TRow>(
                                                this EnumerableRowCollection<TRow> source,
                                                Func<TRow, bool> predicate)
        {
            EnumerableRowCollection<TRow> edt =
                new EnumerableRowCollection<TRow>(source, Enumerable.Where<TRow>(source, predicate), null); //copy constructor
            edt.AddPredicate(predicate);
            return edt;
        }
 
        /// <summary>
        /// LINQ's OrderBy operator for generic EnumerableRowCollection.
        /// </summary>
        public static OrderedEnumerableRowCollection<TRow> OrderBy<TRow, TKey>(
                                                        this EnumerableRowCollection<TRow> source,
                                                        Func<TRow, TKey> keySelector)
        {
            IEnumerable<TRow> ie = Enumerable.OrderBy<TRow, TKey>(source, keySelector);
 
            OrderedEnumerableRowCollection<TRow> edt = new OrderedEnumerableRowCollection<TRow>(source, ie);
            edt.AddSortExpression(keySelector, false, true);
            return edt;
        }
 
        /// <summary>
        /// LINQ's OrderBy operator for generic EnumerableRowCollection.
        /// </summary>
        public static OrderedEnumerableRowCollection<TRow> OrderBy<TRow, TKey>(
                                                        this EnumerableRowCollection<TRow> source,
                                                        Func<TRow, TKey> keySelector,
                                                        IComparer<TKey> comparer)
        {
            IEnumerable<TRow> ie = Enumerable.OrderBy<TRow, TKey>(source, keySelector, comparer);
            OrderedEnumerableRowCollection<TRow> edt = new OrderedEnumerableRowCollection<TRow>(source, ie);
            edt.AddSortExpression(keySelector, comparer, false, true);
            return edt;
        }
 
        /// <summary>
        /// LINQ's OrderByDescending operator for generic EnumerableRowCollection.
        /// </summary>
        public static OrderedEnumerableRowCollection<TRow> OrderByDescending<TRow, TKey>(
                                                        this EnumerableRowCollection<TRow> source,
                                                        Func<TRow, TKey> keySelector)
        {
            IEnumerable<TRow> ie = Enumerable.OrderByDescending<TRow, TKey>(source, keySelector);
 
            OrderedEnumerableRowCollection<TRow> edt = new OrderedEnumerableRowCollection<TRow>(source, ie);
            edt.AddSortExpression(keySelector, true, true);
            return edt;
        }
 
        /// <summary>
        /// LINQ's OrderByDescending operator for generic EnumerableRowCollection.
        /// </summary>
        public static OrderedEnumerableRowCollection<TRow> OrderByDescending<TRow, TKey>(
                                                        this EnumerableRowCollection<TRow> source,
                                                        Func<TRow, TKey> keySelector,
                                                        IComparer<TKey> comparer)
        {
            IEnumerable<TRow> ie = Enumerable.OrderByDescending<TRow, TKey>(source, keySelector, comparer);
 
            OrderedEnumerableRowCollection<TRow> edt = new OrderedEnumerableRowCollection<TRow>(source, ie);
            edt.AddSortExpression(keySelector, comparer, true, true);
            return edt;
        }
 
        /// <summary>
        /// LINQ's ThenBy operator for generic EnumerableRowCollection.
        /// </summary>
        public static OrderedEnumerableRowCollection<TRow> ThenBy<TRow, TKey>(
                                                        this OrderedEnumerableRowCollection<TRow> source,
                                                        Func<TRow, TKey> keySelector)
        {
            IEnumerable<TRow> ie =
                Enumerable.ThenBy<TRow, TKey>((IOrderedEnumerable<TRow>)source.EnumerableRows, keySelector);
 
            OrderedEnumerableRowCollection<TRow> edt =
                new OrderedEnumerableRowCollection<TRow>((EnumerableRowCollection<TRow>)source, ie);
 
            edt.AddSortExpression(keySelector, /*isDesc*/ false, /*isOrderBy*/ false);
            return edt;
        }
 
        /// <summary>
        /// LINQ's ThenBy operator for generic EnumerableRowCollection.
        /// </summary>
        public static OrderedEnumerableRowCollection<TRow> ThenBy<TRow, TKey>(
                                                        this OrderedEnumerableRowCollection<TRow> source,
                                                        Func<TRow, TKey> keySelector,
                                                        IComparer<TKey> comparer)
        {
            IEnumerable<TRow> ie =
                Enumerable.ThenBy<TRow, TKey>((IOrderedEnumerable<TRow>)source.EnumerableRows, keySelector, comparer);
 
            OrderedEnumerableRowCollection<TRow> edt =
                new OrderedEnumerableRowCollection<TRow>((EnumerableRowCollection<TRow>)source, ie);
 
            edt.AddSortExpression(keySelector, comparer, false, false);
            return edt;
        }
 
        /// <summary>
        /// LINQ's ThenByDescending operator for generic EnumerableRowCollection.
        /// </summary>
        public static OrderedEnumerableRowCollection<TRow> ThenByDescending<TRow, TKey>(
                                                        this OrderedEnumerableRowCollection<TRow> source,
                                                        Func<TRow, TKey> keySelector)
        {
            IEnumerable<TRow> ie =
                Enumerable.ThenByDescending<TRow, TKey>((IOrderedEnumerable<TRow>)source.EnumerableRows, keySelector);
 
            OrderedEnumerableRowCollection<TRow> edt =
                new OrderedEnumerableRowCollection<TRow>((EnumerableRowCollection<TRow>)source, ie);
 
            edt.AddSortExpression(keySelector, /*desc*/ true, false);
            return edt;
        }
 
        /// <summary>
        /// LINQ's ThenByDescending operator for generic EnumerableRowCollection.
        /// </summary>
        public static OrderedEnumerableRowCollection<TRow> ThenByDescending<TRow, TKey>(
                                                        this OrderedEnumerableRowCollection<TRow> source,
                                                        Func<TRow, TKey> keySelector,
                                                        IComparer<TKey> comparer)
        {
            IEnumerable<TRow> ie =
                Enumerable.ThenByDescending<TRow, TKey>((IOrderedEnumerable<TRow>)source.EnumerableRows, keySelector, comparer);
 
            OrderedEnumerableRowCollection<TRow> edt =
                new OrderedEnumerableRowCollection<TRow>((EnumerableRowCollection<TRow>)source, ie);
 
            edt.AddSortExpression(keySelector, comparer, true, false);
            return edt;
        }
 
        /// <summary>
        /// Executes a Select (Projection) on EnumerableDataTable. If the selector returns a different
        /// type than the type of rows, then AsLinqDataView is disabled, and the returning EnumerableDataTable
        /// represents an enumerable over the LINQ Query.
        /// </summary>
        public static EnumerableRowCollection<S> Select<TRow, S>(
                                                this EnumerableRowCollection<TRow> source,
                                                Func<TRow, S> selector)
        {
            //Anonymous type or some other type
            //The only thing that matters from this point on is _enumerableRows
 
            IEnumerable<S> typedEnumerable = Enumerable.Select<TRow, S>(source, selector);
 
            // Dont need predicates or sort expression from this point on since we know
            // AsLinqDataView is disabled.
            return new EnumerableRowCollection<S>(((object)source) as EnumerableRowCollection<S>,
                                                  typedEnumerable,
                                                  ((object)selector) as Func<S,S>);
        }
 
        /// <summary>
        /// Casts an EnumerableDataTable_TSource into EnumerableDataTable_TResult
        /// </summary>
        public static EnumerableRowCollection<TResult> Cast<TResult>(this EnumerableRowCollection source)
        {
            // Since Cast does not have the signature Cast_T_R(..) this call is routed
            // through the non-generic base class EnumerableDataTable
 
            if ((null != source) && source.ElementType.Equals(typeof(TResult)))
            {
                return (EnumerableRowCollection<TResult>)(object)source;
            }
            else
            {   //Anonymous type or some other type
                //The only thing that matters from this point on is _enumerableRows
 
                IEnumerable<TResult> typedEnumerable = Enumerable.Cast<TResult>(source);
 
                EnumerableRowCollection<TResult> newEdt = new EnumerableRowCollection<TResult>(
                    typedEnumerable,
                    typeof(TResult).IsAssignableFrom(source.ElementType) && typeof(DataRow).IsAssignableFrom(typeof(TResult)),
                    source.Table);
 
                return newEdt;
            }
        }
    } //end class
}