2009-07-08 27 views
12

Tôi đã gặp phải một chút vấn đề, mà tôi chỉ đơn giản là không thể tìm thấy một công việc tốt xung quanh.Quá tải phương thức chỉ khác nhau theo ràng buộc chung

Tôi muốn có những 3 quá tải:

public IList<T> GetList<T>(string query) where T: string 
public IList<T> GetList<T>(string query) where T: SomeClass 
public IList<T> GetList<T>(string query) where T: struct 

Rõ ràng là khó khăn đầu tiên thậm chí sẽ không biên dịch một mình, vì vậy đó là vấn đề đầu tiên của tôi. (Tôi nhận ra rằng tôi có thể làm cho nó trở thành IList nhưng tôi muốn cùng một cú pháp cho cả ba)

Dù sao thì đây là một phần của trình bao quanh việc thực thi truy vấn SQL đối với cơ sở dữ liệu - tôi muốn trở thành có thể trả về kết quả dưới dạng danh sách các chuỗi (trong trường hợp ai đó chọn cột varchar), danh sách các valuetypes (int, float, bất kỳ) hoặc danh sách các lớp (các lớp này đại diện cho các bảng và do đó chứa nhiều cột)

Tôi hy vọng rằng một phần có phần dễ hiểu :-)

Dù sao thì vấn đề lớn của tôi rõ ràng là tôi không thể thực hiện các quá tải này vì chúng sử dụng cùng tên và danh sách tham số. Ngoài ra tôi không thể kết hợp chúng vào cùng một phương pháp, vì tôi cần phải gọi một phương thức trên SomeClass trong việc thực hiện đó, vì vậy trừ khi tôi muốn làm một số typecasting nặng, hoặc tệ hơn, phản ánh - tôi cần sự hạn chế đó.

Tôi nhận ra rằng những gì tôi đang cố gắng làm là không thể, vì vậy những gì tôi đang tìm kiếm là một cách tiếp cận tốt, điều đó sẽ bắt chước ý định của tôi.

Nếu một số này là một chút không rõ ràng, đừng ngần ngại hỏi :-)

Edit:

Đây là mã hiện tại của tôi cho "nơi T: SomeClass" phiên bản. Tôi đang cố gắng để hỗ trợ thêm cho chuỗi/valuetypes để mã hiện tại này, vì vậy có lẽ cách tiếp cận ban đầu của tôi chỉ là đồng bằng sai - bất kỳ ý tưởng được hoan nghênh về cơ bản :-)

public IList<TValue> GetList<TValue>(string query) where TValue : DbTable, new() 
{ 
    DataSet dataSet = GetDataSet(query); 
    IList<TValue> result = new List<TValue>(); 

    if (dataSet.Tables.Count > 0) 
    { 
     foreach (DataRow row in dataSet.Tables[0].Rows) 
     { 
      TValue col = new TValue(); 
      col.Fill(row); 
      result.Add(col); 
     } 
    } 

    return result; 
} 

Như bạn có thể thấy tôi cần phải chính xác loại của DbTable để tạo ra hàm tạo mới thích hợp. Điền là một phương thức trừu tượng của DbTable (là một lớp trừu tượng).

Trả lời

10

Như bạn lưu ý; không có bất kỳ lựa chọn tốt cho việc này. Bạn có thể xem xét các tên khác nhau (chứ không phải là quá tải) - GetStringList v.v.

Tuy nhiên, tôi tự hỏi liệu việc giảm ràng buộc có đơn giản hơn hay không. Một loại kiểm tra duy nhất với "như" không chính xác là "nặng" loại đúc, và nó có thể tiết kiệm rất nhiều đau đớn.

+0

Có tên khác nhau rất đơn giản, tuy nhiên tôi muốn làm cho nó gần giống như nó chỉ là một và cùng một phương pháp, mà acceps những khó khăn này. Tôi có thể tạo một GetList mà không bị ràng buộc, và sau đó ném một ngoại lệ nếu kiểu đó sai - tuy nhiên trong trường hợp SomeClass, nó thực sự là lớp kế thừa SomeClass, và tôi cần loại chính xác, vì tôi mới() chúng. Đợi một chút và tôi sẽ đăng GetList hiện tại của mình trong đó mã T: SomeClass. – Steffen

+0

Trong trường hợp đó, nó có thể lộn xộn với 'MakeGenericMethod' vv; không phải là một lựa chọn tốt. –

+0

Chính xác - và bạn nói đúng rằng việc kiểm tra kiểu đơn giản cho các chuỗi và valuetypes không phải là phiền hà. Nó nhận được các loại con ra khỏi DbTable tôi đang lo lắng về. – Steffen

0

thì sao?

public IList<T> GetList<T>(string query) where T : new() 
{ 
    // whatever you need to distinguish, this is a guess: 
    if (typeof(T).IsPrimitiveValue) 
    { 
    GetPrimitiveList<T>(query); 
    } 
    else if (typeof(T) == typeof(string)) 
    { 
    GetStringList<T>(query); 
    } 
    else 
    { 
    GetEntityList<T>(query); 
    } 

} 

private IList<T> GetStringList<T>(string query) 

private IList<T> GetPrimitiveList<T>(string query) 

private IList<T> GetEntityList<T>(string query) 
+0

Có điều đó gần như là công việc, vấn đề duy nhất là GetEntityList - như bạn có thể thấy từ ví dụ mã của tôi, tôi cần có khả năng new() T và gọi Fill trên nó - không thể nào nếu không có ràng buộc * hoặc * reflection (mà tôi không muốn) Tuy nhiên, phần còn lại sẽ hoạt động tốt. – Steffen

+0

Bạn sẽ cần kiểm tra thời gian chạy để thực hiện giao diện ('as'). Phản ánh là không cần thiết. Hoặc - làm cho các phương thức có tên riêng (GetEntityList) công khai và gọi nó trực tiếp. –

+0

Stefan - Tôi có ít nhất một tá triển khai của DbTable (vì tôi có một lớp trên mỗi bảng trong cơ sở dữ liệu của mình), vì vậy việc thử nghiệm với không thực sự khả thi, bên cạnh việc triển khai thường nằm ngoài phạm vi của thư viện. Để gọi trực tiếp, tôi bắt đầu tin rằng thực tế là giải pháp duy nhất: -/ – Steffen

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