2009-05-06 26 views
5

Tôi đã nhìn thấy một số mẫu sử dụng 'T' để làm cho một phương pháp có thể tái sử dụng cho các bộ sưu tập chung của các lớp khác nhau, nhưng tôi chưa bao giờ thực sự hiểu được hoặc hiểu mẫu.Làm thế nào để cấu trúc lại 2 phương pháp tương tự này thành một?

Tôi tự hỏi liệu có thể đặt 2 phương pháp dưới đây vào một và những nhược điểm của việc này sẽ là (hiệu suất khôn ngoan).

Bất kỳ ai?

 [NonAction] 
     public List<SelectListItem> ToSelectList(IEnumerable<Department> departments, string defaultOption) 
     { 
      var items = departments.Select(d => new SelectListItem() { Text = d.Code + " - " + d.Description, Value = d.Id.ToString() }).ToList(); 
      items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
      return items; 
     } 

     [NonAction] 
     public List<SelectListItem> ToSelectList(IEnumerable<Function> functions, string defaultOption) 
     { 
      var items = functions.Select(f => new SelectListItem() { Text = f.Description, Value = f.Id.ToString() }).ToList(); 
      items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
      return items; 
     } 

SOLUTION

Các giải pháp mà tôi đã sử dụng:

sử dụng

var departmentItems = departments.ToSelectList(d => d.Code + " - " + d.Description, d => d.Id.ToString(), " - "); 
var functionItems = customerFunctions.ToSelectList(f => f.Description, f => f.Id.ToString(), " - "); 

với

public static class MCVExtentions 
    { 
     public static List<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> text, Func<T, string> value, string defaultOption) 
     { 
      var items = enumerable.Select(f => new SelectListItem() { Text = text(f), Value = value(f) }).ToList(); 
      items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
      return items; 
     } 
    } 

Trả lời

7

Without implementiong một giao diện phổ biến như @Grzenio gợi ý, bạn có thể sử dụng một phương pháp chung chung như thế này:

public List<SelectListItem> ToSelectList<T>(IEnumerable<T> enumerable, Func<T, string> text, Func<T, string> value, string defaultOption) 
    { 
     var items = enumerable.Select(f => new SelectListItem() { Text = text(f), Value = value(f) }).ToList(); 
     items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
     return items; 
    } 

    // use like 

    t.ToSelectList(departments, d => d.Code + " - " + d.Description, d => d.Id.ToString(), "default"); 
    t.ToSelectList(functions, f => f.Description, f => f.Id.ToString(), "default"); 
+0

Cảm ơn!Đây là thứ tôi đang tìm kiếm ngay từ đầu. Tôi sẽ cố gắng để thực hiện của bạn và xem nếu tôi thích làm việc với nó –

+0

Hey câu trả lời của tôi là giống hệt nhau và đăng ba phút trước khi câu trả lời này được nêu ra câu trả lời này được 3 phiếu và số không của tôi! OK Tôi sẽ bỏ phiếu dù sao, nếu chỉ để có các tham số chung cho Chức năng theo thứ tự đúng ... – Motti

+1

ToSelectList cũng có thể được thực hiện một phương thức mở rộng. – idursun

8

Cách trường cũ sẽ tạo ra một giao diện chung cho cả cục và chức năng:

interface A 
{ 
int ID{get;} 
string Description{get;} 
} 

Bạn thực hiện Mô tả về Bộ để trở d.Code + " - " + d.Description. và viết các chức năng để sử dụng giao diện này để thay thế lớp bê tông:

[NonAction] 
    public List<SelectListItem> ToSelectList(IEnumerable<A> as, string defaultOption) 
    { 
     var items = as.Select(a => new SelectListItem() { Text = a.Description, Value = a.Id.ToString() }).ToList(); 
     items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
     return items; 
    } 

EDIT: Về sử dụng Generics, nó sẽ không giúp được gì nhiều trong trường hợp này, bởi vì

  • các đối tượng bạn đang đi qua cầu để triển khai Id và Mô tả
  • bạn không trả lại các đối tượng này, do đó, về khía cạnh này bạn không phải quan tâm đến tính an toàn loại của generics
+0

Ofcourse! Cảm ơn. Tôi đã quá mắc kẹt suy nghĩ về những mẫu với 'T' mà tôi đã không nhận ra một giao diện là tất cả những gì tôi cần. Cảm ơn rất nhiều. –

+2

Tôi sẽ nói sử dụng generics và chức năng sẽ là một điều tốt hơn để làm trong trường hợp này. Sau đó, bạn không phải ép buộc một loạt các lớp vào thực hiện một giao diện. Bạn có thể muốn sử dụng hàm ToSelectList đó trên một lớp không có ID hoặc Mô tả, và khi thêm nó sẽ không hợp lý (hoặc ví dụ thuộc tính Mô tả thực sự nên được gọi là cái gì khác). – Svish

+0

Cảm ơn Svish. Điểm tốt. –

4

Trong thực tế, bạn có thể làm điều đó với một sự kết hợp của generics và chức năng, một cái gì đó dọc theo dòng này (chưa được kiểm tra có thể thậm chí không biên dịch).

[NonAction] 
public List<SelectListItem> ToSelectList<T>(IEnumerable<T> en, 
              Function<string, T> text, 
              Function<string, T> value, 
              string defaultOption) 
{ 
    var items = en.Select(x => new SelectListItem() { Text = text(x) , Value = value(x) }).ToList(); 
    items.Insert(0, new SelectListItem() { Text = defaultOption, Value = "-1" }); 
    return items; 
} 

Sau đó, bạn có thể gửi đến nó bằng hàm lambda thích hợp (hoặc gọi trực tiếp).

[NonAction] 
public List<SelectListItem> ToSelectList(IEnumerable<Department> departments, 
             string defaultOption) 
{ 
    return ToSelectList<Department>(departments, d => d.Code + '-' + d.Description, d => d.Id.ToString(), defaultOption); 

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