Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataSet / System / Data / SortExpressionBuilder.cs / 1305376 / SortExpressionBuilder.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
// [....]
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Data;
using System.Linq;
using System.Diagnostics;
namespace System.Data
{
///
/// This class represents a combined sort expression build using mutiple sort expressions.
///
///
internal class SortExpressionBuilder : IComparer>
{
/**
* This class ensures multiple orderby/thenbys are handled correctly. Its semantics is as follows:
*
* Query 1:
* orderby a
* thenby b
* orderby c
* orderby d
* thenby e
*
* is equivalent to:
*
* Query 2:
* orderby d
* thenby e
* thenby c
* thenby a
* thenby b
*
**/
//Selectors and comparers are mapped using the index in the list.
//E.g: _comparers[i] is used with _selectors[i]
LinkedList> _selectors = new LinkedList>();
LinkedList> _comparers = new LinkedList>();
LinkedListNode> _currentSelector = null;
LinkedListNode> _currentComparer = null;
///
/// Adds a sorting selector/comparer in the correct order
///
internal void Add(Func keySelector, Comparison compare, bool isOrderBy)
{
Debug.Assert(keySelector != null);
Debug.Assert(compare != null);
//Inputs are assumed to be valid. The burden for ensuring it is on the caller.
if (isOrderBy)
{
_currentSelector = _selectors.AddFirst(keySelector);
_currentComparer = _comparers.AddFirst(compare);
}
else
{
//ThenBy can only be called after OrderBy
Debug.Assert(_currentSelector != null);
Debug.Assert(_currentComparer != null);
_currentSelector = _selectors.AddAfter(_currentSelector, keySelector);
_currentComparer = _comparers.AddAfter(_currentComparer, compare);
}
}
///
/// Represents a Combined selector of all selectors added thusfar.
///
/// List of 'objects returned by each selector'. This list is the combined-selector
public List Select(T row)
{
List result = new List();
foreach (Func selector in _selectors)
{
result.Add(selector(row));
}
return result;
}
///
/// Represents a Comparer (of IComparer) that compares two combined-selectors using
/// provided comparers for each individual selector.
/// Note: Comparison is done in the order it was Added.
///
/// Comparison result of the combined Sort comparer expression
public int Compare(List a, List b)
{
Debug.Assert(a.Count == Count);
int i = 0;
foreach (Comparison compare in _comparers)
{
int result = compare(a[i], b[i]);
if (result != 0)
{
return result;
}
i++;
}
return 0;
}
internal int Count
{
get
{
Debug.Assert(_selectors.Count == _comparers.Count); //weak now that we have two dimensions
return _selectors.Count;
}
}
///
/// Clones the SortexpressionBuilder and returns a new object
/// that points to same comparer and selectors (in the same order).
///
///
internal SortExpressionBuilder Clone()
{
SortExpressionBuilder builder = new SortExpressionBuilder();
foreach (Func selector in _selectors)
{
if (selector == _currentSelector.Value)
{
builder._currentSelector = builder._selectors.AddLast(selector);
}
else
{
builder._selectors.AddLast(selector);
}
}
foreach (Comparison comparer in _comparers)
{
if (comparer == _currentComparer.Value)
{
builder._currentComparer = builder._comparers.AddLast(comparer);
}
else
{
builder._comparers.AddLast(comparer);
}
}
return builder;
}
///
/// Clones the SortExpressinBuilder and casts to type TResult.
///
internal SortExpressionBuilder CloneCast()
{
SortExpressionBuilder builder = new SortExpressionBuilder();
foreach (Func selector in _selectors)
{
if (selector == _currentSelector.Value)
{
builder._currentSelector = builder._selectors.AddLast(r => selector((T)(object)r));
}
else
{
builder._selectors.AddLast(r => selector((T)(object)r));
}
}
foreach (Comparison comparer in _comparers)
{
if (comparer == _currentComparer.Value)
{
builder._currentComparer = builder._comparers.AddLast(comparer);
}
else
{
builder._comparers.AddLast(comparer);
}
}
return builder;
}
} //end SortExpressionBuilder
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
// [....]
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Data;
using System.Linq;
using System.Diagnostics;
namespace System.Data
{
///
/// This class represents a combined sort expression build using mutiple sort expressions.
///
///
internal class SortExpressionBuilder : IComparer>
{
/**
* This class ensures multiple orderby/thenbys are handled correctly. Its semantics is as follows:
*
* Query 1:
* orderby a
* thenby b
* orderby c
* orderby d
* thenby e
*
* is equivalent to:
*
* Query 2:
* orderby d
* thenby e
* thenby c
* thenby a
* thenby b
*
**/
//Selectors and comparers are mapped using the index in the list.
//E.g: _comparers[i] is used with _selectors[i]
LinkedList> _selectors = new LinkedList>();
LinkedList> _comparers = new LinkedList>();
LinkedListNode> _currentSelector = null;
LinkedListNode> _currentComparer = null;
///
/// Adds a sorting selector/comparer in the correct order
///
internal void Add(Func keySelector, Comparison compare, bool isOrderBy)
{
Debug.Assert(keySelector != null);
Debug.Assert(compare != null);
//Inputs are assumed to be valid. The burden for ensuring it is on the caller.
if (isOrderBy)
{
_currentSelector = _selectors.AddFirst(keySelector);
_currentComparer = _comparers.AddFirst(compare);
}
else
{
//ThenBy can only be called after OrderBy
Debug.Assert(_currentSelector != null);
Debug.Assert(_currentComparer != null);
_currentSelector = _selectors.AddAfter(_currentSelector, keySelector);
_currentComparer = _comparers.AddAfter(_currentComparer, compare);
}
}
///
/// Represents a Combined selector of all selectors added thusfar.
///
/// List of 'objects returned by each selector'. This list is the combined-selector
public List Select(T row)
{
List result = new List();
foreach (Func selector in _selectors)
{
result.Add(selector(row));
}
return result;
}
///
/// Represents a Comparer (of IComparer) that compares two combined-selectors using
/// provided comparers for each individual selector.
/// Note: Comparison is done in the order it was Added.
///
/// Comparison result of the combined Sort comparer expression
public int Compare(List a, List b)
{
Debug.Assert(a.Count == Count);
int i = 0;
foreach (Comparison compare in _comparers)
{
int result = compare(a[i], b[i]);
if (result != 0)
{
return result;
}
i++;
}
return 0;
}
internal int Count
{
get
{
Debug.Assert(_selectors.Count == _comparers.Count); //weak now that we have two dimensions
return _selectors.Count;
}
}
///
/// Clones the SortexpressionBuilder and returns a new object
/// that points to same comparer and selectors (in the same order).
///
///
internal SortExpressionBuilder Clone()
{
SortExpressionBuilder builder = new SortExpressionBuilder();
foreach (Func selector in _selectors)
{
if (selector == _currentSelector.Value)
{
builder._currentSelector = builder._selectors.AddLast(selector);
}
else
{
builder._selectors.AddLast(selector);
}
}
foreach (Comparison comparer in _comparers)
{
if (comparer == _currentComparer.Value)
{
builder._currentComparer = builder._comparers.AddLast(comparer);
}
else
{
builder._comparers.AddLast(comparer);
}
}
return builder;
}
///
/// Clones the SortExpressinBuilder and casts to type TResult.
///
internal SortExpressionBuilder CloneCast()
{
SortExpressionBuilder builder = new SortExpressionBuilder();
foreach (Func selector in _selectors)
{
if (selector == _currentSelector.Value)
{
builder._currentSelector = builder._selectors.AddLast(r => selector((T)(object)r));
}
else
{
builder._selectors.AddLast(r => selector((T)(object)r));
}
}
foreach (Comparison comparer in _comparers)
{
if (comparer == _currentComparer.Value)
{
builder._currentComparer = builder._comparers.AddLast(comparer);
}
else
{
builder._comparers.AddLast(comparer);
}
}
return builder;
}
} //end SortExpressionBuilder
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.