title: Sort rows of dynamic datatable by multiple columns using a IComparer<T> typed class
body: <p>I have an extension method that am trying to sort the rows of a datatable by multiple columns using a IComparer typed class for at least one of the sortings.</p>
  
  <p>The datatable is created with columns whose name and datatype are only known at runtime.  The sort string ("Title ASC, PostedDate DESC") is also created at runtime.  </p>
  
  <p>So say my table has columns: ID , Name , PostedDate , Num1 .  My sorting string was "PostedDate DESC, Name ASC", and during the sorting of string column "Name", I want to use custom class of  </p>
  
  <pre><code>NaturalSortComparer : IComparer&lt;string&gt;
  </code></pre>
  
  <p>I was trying to use the specified IComparer object in the OrderBy call if the column's dataType equaled the TComparerType, but I guess that "the type arguments cannot be inferred from my usage".  </p>
  
  <p>Does anyone have any idea of a way I can pull this off?  Thanks in advance.</p>
  
  <pre><code>public static EnumerableRowCollection&lt;DataRow&gt; OrderBy&lt;TComparerType&gt;(
      this EnumerableRowCollection&lt;DataRow&gt; rows, DataTable table, string orderBy, IComparer&lt;TComparerType&gt; comparer)
  {
      if (table == null || string.IsNullOrWhiteSpace(orderBy))
      {
          return rows;
      }
  
      OrderedEnumerableRowCollection&lt;DataRow&gt; orderedRows = null;
      foreach (string sortString in orderBy.Split(new[] { "," }, StringSplitOptions.None))
      {
          var trimmedSortString = sortString.Trim();
  
          int directionIndex = trimmedSortString.IndexOf(" DESC", StringComparison.OrdinalIgnoreCase);
          bool isDescending = directionIndex != -1;
  
          string columnName = isDescending ? trimmedSortString.Substring(0, directionIndex) : trimmedSortString;
          Type columnType = table.Columns[columnName].DataType;
  
          Func&lt;DataRow,dynamic&gt; selectorFunc = (row =&gt; RowSelectors[columnType](row, columnName));
  
          Type comparerTypeParameter = comparer == null ? null : typeof(TComparerType);
          if (orderedRows == null)
          {
              if (columnType == comparerTypeParameter)
              {
                  orderedRows = isDescending 
                      ? rows.OrderByDescending(selectorFunc, comparer) 
                      : rows.OrderBy(selectorFunc, comparer);
              }
              else
              {
                  orderedRows = isDescending 
                      ? rows.OrderByDescending(selectorFunc) 
                      : rows.OrderBy(selectorFunc);
              }
          }
          else
          {
              if (columnType == comparerTypeParameter)
              {
                  orderedRows = isDescending 
                      ? orderedRows.ThenByDescending(selectorFunc, comparer) 
                      : orderedRows.ThenBy(selectorFunc, comparer);
              }
              else
              {
                  orderedRows = isDescending 
                      ? rows.OrderByDescending(selectorFunc) 
                      : rows.OrderBy(selectorFunc);
              }
          }
      }
      return orderedRows ?? rows;
  }
  
  
  private static readonly Dictionary&lt;Type, Func&lt;DataRow, string, dynamic&gt;&gt; RowSelectors =
      new Dictionary&lt;Type, Func&lt;DataRow, string, dynamic&gt;&gt;
  {
      {typeof(string),   (row,colName)=&gt;row.Field&lt;string&gt;(colName)},
      {typeof(decimal),  (row,colName)=&gt;row.Field&lt;decimal&gt;(colName)},
      {typeof(int),      (row,colName)=&gt;row.Field&lt;int&gt;(colName)},
      {typeof(short),    (row,colName)=&gt;row.Field&lt;short&gt;(colName)},
      {typeof(float),    (row,colName)=&gt;row.Field&lt;float&gt;(colName)},
      {typeof(double),   (row,colName)=&gt;row.Field&lt;double&gt;(colName)},
      {typeof(bool),     (row,colName)=&gt;row.Field&lt;bool&gt;(colName)},
      {typeof(DateTime), (row,colName)=&gt;row.Field&lt;DateTime&gt;(colName)},
      {typeof(TimeSpan), (row,colName)=&gt;row.Field&lt;TimeSpan&gt;(colName)}
  };
  </code></pre>