2011-11-22 69 views
0

我想调用一个类上的方法来对数据进行排序,直到调用该方法时才知道数据类型。动态类型调用通用方法(.net 3.5)

下面是试图调用泛型方法的排序过程的代码:

public void Sort(LiteTableColumn column, LiteSortOrder sortOrder) 
{ 
    column.Sort(sortOrder); 

    //create an array of the values 
    object[] values = new object[_rowCount]; 
    for (int i = 0; i < _rowCount; i++) 
    { 
     values[i] = this.GetValue(column.Index, i); 
    } 

    Type sortType = typeof(QuickSort<>); 
    Type constructedClass = sortType.MakeGenericType(Type.GetType("System." + column.DataType)); 

    object created = Activator.CreateInstance(constructedClass); 
    _sortKey = (int[])sortType.GetMethod("Sort").MakeGenericMethod(Type.GetType("System." + column.DataType)).Invoke(constructedClass, new object[] { values }); 
} 

我在这条线得到一个错误:

_sortKey = (int[])sortType.GetMethod("Sort").MakeGenericMethod(Type.GetType("System." + column.DataType)).Invoke(constructedClass, new object[] { values }); 

错误:

{"Int32[] Sort(T[], Test_SQL_Stream.LiteObjects.LiteSortOrder) is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true."} 

我不确定为什么会发生这种情况。难道是因为我的QuickSort类有T : IComparable

这里是快速排序类

public class QuickSort<T> where T : IComparable 
{ 
    /// <summary> 
    /// Sorts a given array of data in an ascending/descending fashion 
    /// </summary> 
    public QuickSort() 
    { 

    } 

    /// <summary> 
    /// Sorts the items in an order specifies & returns an index that reflects the sorted values 
    /// </summary> 
    /// <param name="sortArray">The array of values to sort (must implement IComparable)</param> 
    /// <param name="direction">The order to sort. Unsorted is not a valid parameter</param> 
    /// <returns></returns> 
    public int[] Sort(T[] sortArray, LiteSortOrder direction) 
    { 
     int rows = sortArray.Length; 
     int[] index = new int[rows]; 

     //populate the index 
     for (int i = 0; i < rows; i++) 
     { 
      index[i] = i; 
     } 

     //raise an error in case the sort direction is set at unsorted and return the original list 
     if (direction == LiteSortOrder.Unsorted) 
     { 
      new InvalidOperationException("Unable to sort items in: LiteSortOrder.Unsorted order"); 
      return index; 
     } 

     //sort the values 
     quickSort(sortArray, index, 0, rows - 1); 

     //if it should be descending order, reverse the items order 
     if (direction == LiteSortOrder.Descending) 
     { 
      int t; 
      int i1 = 0; 
      int i2 = rows - 1; 

      while (i1 < i2) 
      { 
       t = index[i1]; 
       index[i1] = index[i2]; 
       index[i2] = t; 
       i1++; 
       i2--; 
      } 
     } 

     //return the sorted index 
     return index; 
    } 

    private static void quickSort(T[] List, int[] RefList, int StartIdx, int EndIdx) 
    { 
     int Lo, Hi, T; 
     T Mid; 

     Lo = StartIdx; 
     Hi = EndIdx; 
     Mid = List[RefList[(Lo + Hi)/2]]; 

     do 
     { 
      while (List[RefList[Lo]].CompareTo(Mid) < 0) Lo++; 
      while (List[RefList[Hi]].CompareTo(Mid) > 0) Hi--; 
      if (Lo <= Hi) 
      { 
       T = RefList[Lo]; 
       RefList[Lo] = RefList[Hi]; 
       RefList[Hi] = T; 
       Lo++; 
       Hi--; 
      } 
     } while (Lo <= Hi); 
     if (Hi > StartIdx) quickSort(List, RefList, StartIdx, Hi); 
     if (Lo < EndIdx) quickSort(List, RefList, Lo, EndIdx); 
    } 
} 

编辑:所以有关使用的Array.Sort的意见后,我看着这个方法还。这是远远超过我的快速排序的方法更快(我使用字符串,而不是仿制药测试):

对于那些你想知道谁,这里的结果:

Populate Strings:159ms 
Populate Objects: 53ms 
Array.Sort w/Key: 10ms 
Array.Sort w/o Key: 229ms 
QuickSort w/strings: 231ms 

,代码:

watch.Start(); 
     string[] values = new string[_rowCount]; 
     for (int i = 0; i < _rowCount; i++) 
     { 
      if (this.GetValue(column.Index, i) != null) 
       values[i] = this.GetValue(column.Index, i).ToString(); 
      else 
       values[i] = ""; 
     } 
     Debug.WriteLine("Populate Strings:" +watch.ElapsedMilliseconds.ToString()); 
     watch.Reset(); 
     watch.Start(); 
     object[] objVal = new object[_rowCount]; 

     for (int i = 0; i < _rowCount; i++) 
     { 
      _sortKey[i] = i; 
      objVal[i] = this.GetValue(column.Index, i); 
     } 
     Debug.WriteLine("Populate Objects: " + watch.ElapsedMilliseconds.ToString()); 
     watch.Reset(); 
     watch.Start(); 
     Array.Sort(_sortKey, objVal); 
     Debug.WriteLine("Array.Sort w/Key: " + watch.ElapsedMilliseconds.ToString()); 
     watch.Reset(); 
     watch.Start(); 
     Array.Sort(objVal); 
     Debug.WriteLine("Array.Sort w/o Key: " +watch.ElapsedMilliseconds.ToString()); 
     watch.Reset(); 
     watch.Start(); 
     QuickSort sorter = new QuickSort(); 
     sorter.Sort(values, LiteSortOrder.Ascending); 
     Debug.WriteLine("QuickSort w/strings: " + watch.ElapsedMilliseconds.ToString()); 
+0

我会建议这样做,每个类必须实现而不是使用“动态通用”的接口。 – mydogisbox

+0

'Type.GetType'很慢,应尽可能避免。 – SLaks

+1

为什么不调用'Array.Sort'? – SLaks

回答

2

Sort方法是在通用类非泛型方法。

MakeGenericMethod只能在通用方法上调用–方法自己需要一个通用参数。
一旦你构建了封闭的通用QuickSort<Something>类型,Sort是一个正常的方法。

+0

谢谢,这是有道理的 – ChandlerPelhams

0

Sort函数不是通用的。它仅仅在泛型类中,但它本身不是泛型的。因此:

_sortKey = (int[])sortType.GetMethod("Sort").Invoke(constructedClass, new object[] { values });