2009-09-10 34 views
5

tôi thấy các chức năng sau đây trong một bài viết cho phép một để đặt hàng dữ liệu sử dụng một biểu thức tổng quát:Vấn đề với chức năng Generic LINQ OrderBy

public static IOrderedQueryable<T> OrderBy<T, TKey>(
    this IQueryable<T> source, Expression<Func<T, TKey>> func, bool isDescending) { 
    return isDescending ? source.OrderByDescending(func) : source.OrderBy(func); 
} 

Khi tôi cố gắng sử dụng chức năng này tôi nhận được một lỗi nói rằng "Các loại hoặc tên namespace "TKey' không thể được tìm thấy (là bạn thiếu một chỉ thị sử dụng hoặc tham khảo một hội?)" tôi đang làm một cái gì đó ngớ ngẩn ở đây nhưng tôi không thể hình dung nó ra

Edit:..

Sau khi nghiên cứu thêm một chút, tôi nghĩ rằng vấn đề của tôi là xây dựng Expr ession mà tôi vượt qua nó. Có thể xây dựng một biểu thức có thể chứa các loại khác nhau không? Giả sử tập dữ liệu của tôi có chuỗi, int và bool và tôi muốn sử dụng hàm chung ở trên để sắp xếp theo bất kỳ mục nào. Làm thế nào để tôi làm điều này?

Tôi có điều này làm việc bây giờ:

if (IsString) 
{ 
    Expression<Func<T, string>> expString = ...; 
    // call orderBy with expString 
} 
else if (IsInt) 
{ 
    Expression<Func<T, int>> expInt; 
    // call orderBy w/ expInt 
} 
: 

Tôi muốn một cái gì đó như:

Expression<Func<T, {something generic!}>> exp; 
if (IsString) 
    exp = ...; 
else if (IsInt) 
    exp = ...; 
: 
// call orderBy with exp 
+0

Điều này có vẻ ổn. Bạn sử dụng phương pháp này như thế nào? Bạn đã thêm nó vào một lớp tĩnh? – BFree

Trả lời

2

Mục tiêu của tôi là xóa bỏ rất nhiều mã lặp lại. Ngoài việc xử lý hàm "OrderBy" tăng dần/giảm dần của tôi, việc xử lý một số logic phổ biến khác cũng tốt. Giả sử định nghĩa chức năng trong bài đăng gốc, người ta chỉ có thể làm điều này:

if ({need to sort by integer}) 
    query = OrderBy(objectT, a => a.myIntegerField, asc); 
else if ({need to sort by string}) 
    query = OrderBy(objectT, a=> a.myStringField, asc); 
: 
1

Khái niệm chỉ có thể có một loại; câu trả lời ưa thích của tôi ở đây sẽ là một cái gì đó như:

IQueryable<T> query = ... 
if({case 1}) { 
    query = query.OrderBy(x=>x.SomeValue); 
} else if({case 2}) { 
    query = query.OrderBy(x=>x.SomeOtherValue); 
} ... 

Tuy nhiên, nếu bạn muốn làm điều gì đó linh hoạt hơn, có lẽ bạn sẽ cần phải nhận được vào tùy chỉnh Expression văn bản; một cái gì đó more like this.

+0

Đó là những gì tôi đã có ban đầu, nhưng tôi đã kết thúc với một tấn "trùng lặp" mã do thực tế tôi có nhiều lĩnh vực và cần phải xử lý các loại tăng dần/giảm dần. Câu trả lời tôi đăng dường như hoạt động tốt. – ejwipp

4

Một quan sát nhanh: Bạn không thực sự cần sử dụng biểu thức lambda (Expression<Func<T,TKey>>). Một đại biểu đơn giản (Func<T,TKey>) là tốt.

Điều đó nói rằng, tôi nghĩ câu trả lời bạn có thể tìm kiếm là thế này:

Func<T,IComparable> func = null; 
if (IsString) 
    func = (T a) => a.SomeStringValue; 
else if (IsInt) 
    func = (T a) => a.SomeIntValue; 
// call orderBy with exp 
+0

Điều này có vẻ như những gì tôi đang tìm kiếm. Tuy nhiên, tôi chơi xung quanh với nó một chút và không thể làm cho nó để biên dịch. Khi tôi cố gắng để vượt qua func vào một chức năng OrderBy trình biên dịch phàn nàn. Phương pháp của bạn sẽ hơi sạch hơn nếu nó hoạt động, nhưng tiếc là tôi không thể dành nhiều thời gian hơn cho nó ngay bây giờ. – ejwipp

+1

Khi bạn có thời gian, hãy cho tôi biết lỗi trình biên dịch bạn đang gặp phải là gì. – jpbochi

+0

Cuối cùng tôi cũng đã quay lại điều này. Tôi nghĩ rằng vấn đề là trong chức năng orderBy tùy chỉnh của tôi, tôi thực hiện một cuộc gọi đến ThenBy mà không có một đối số Func - nó đòi hỏi các biểu thức lambda. – ejwipp

0

Hãy xem this answer

xử lý chung của tôi cho phân loại là:

  • "dgvProcessList" là DataGridView tôi
  • "Process" là đối tượng của tôi binded đến nó
  • "e" là DataGridViewCellMouseEventArgs tôi

      PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First(); 
         if (isSortedASC == true) 
          dgvProcessList.DataSource = ((List<Process>)dgvProcessList.DataSource).OrderByDescending(x => column.GetValue(x, null)).ToList(); 
         else 
          dgvProcessList.DataSource = ((List<Process>)dgvProcessList.DataSource).OrderBy(x => column.GetValue(x, null)).ToList(); 
    
         isSortedASC = !isSortedASC; 
         dgvProcessList.ClearSelection(); 
    

Chúc mừng

Các vấn đề liên quan