2008-08-18 46 views
10

Trước hết, tôi hiểu lý do tại sao giao diện hoặc lớp trừu tượng (trong thuật ngữ .NET/C#) không thể có phương thức tĩnh trừu tượng. Câu hỏi của tôi sau đó tập trung hơn vào giải pháp thiết kế tốt nhất. Những gì tôi muốn là một tập hợp các lớp "helper", tất cả đều có các phương thức tĩnh riêng của chúng, nếu tôi nhận các đối tượng A, B và C từ một nhà cung cấp bên thứ ba, tôi có thể có các lớp trợ giúp với các phương thức nhưPhương pháp tĩnh trong giao diện/lớp trừu tượng

 
AHelper.RetrieveByID(string id); 
AHelper.RetrieveByName(string name); 
AHelper.DumpToDatabase(); 

Vì các lớp AHelper, BHelper và CHelper của tôi về cơ bản sẽ có cùng phương pháp, có vẻ như có ý nghĩa khi di chuyển các phương thức này đến giao diện mà các lớp này bắt nguồn từ đó. Tuy nhiên, muốn những phương thức này là tĩnh ngăn cản tôi có một giao diện chung hoặc lớp trừu tượng cho tất cả chúng để lấy được.

tôi luôn luôn có thể thực hiện các phương pháp này không tĩnh và sau đó nhanh chóng các đối tượng đầu tiên như

 
AHelper a = new AHelper(); 
a.DumpToDatabase(); 

Tuy nhiên, mã này dường như không phải là trực quan đối với tôi. Đề xuất của bạn là gì? Tôi có nên từ bỏ việc sử dụng giao diện hoặc lớp trừu tượng hoàn toàn (tình huống hiện tại của tôi) hay điều này có thể được tái cấu trúc để hoàn thành thiết kế mà tôi đang tìm kiếm?

Trả lời

3

Nhìn tại your response Tôi đang suy nghĩ theo các dòng sau:

  • Bạn chỉ có thể có phương thức tĩnh có tham số kiểu và thực hiện logic dự kiến ​​dựa trên loại.
  • Bạn có thể tạo phương thức ảo trong cơ sở trừu tượng của mình, nơi bạn chỉ định SQL trong lớp cụ thể. Vì vậy, có chứa tất cả các mã phổ biến được yêu cầu bởi cả hai (ví dụ: thực hiện lệnh và trả về đối tượng) trong khi đóng gói các bit "chuyên gia" (ví dụ: SQL) trong các lớp con.

Tôi thích tùy chọn thứ hai, mặc dù tất nhiên là tùy chọn của bạn. Nếu bạn cần tôi đi vào chi tiết hơn nữa, xin vui lòng cho tôi biết và tôi sẽ được hạnh phúc để chỉnh sửa/cập nhật :)

+0

IMHO: Tùy chọn đầu tiên sẽ tốt hơn là chung chung để suy luận kiểu có thể được sử dụng mà thậm chí còn tốt hơn. –

1

Trong C# 3.0, phương pháp tĩnh có thể được sử dụng trên giao diện như thể chúng là một phần của họ bằng cách sử dụng phương pháp khuyến nông, như với DumpToDatabase() dưới đây:

static class HelperMethods 
{ //IHelper h = new HeleperA(); 
    //h.DumpToDatabase() 
    public static void DumpToDatabase(this IHelper helper) { /* ... */ } 

    //IHelper h = a.RetrieveByID(5) 
    public static IHelper RetrieveByID(this ObjectA a, int id) 
    { 
      return new HelperA(a.GetByID(id)); 
    } 

    //Ihelper h = b.RetrieveByID(5)  
    public static IHelper RetrieveByID(this ObjectB b, int id) 
    { 
      return new HelperB(b.GetById(id.ToString())); 
    } 
} 
2

Cá nhân tôi có lẽ sẽ đặt câu hỏi về lý do tại sao mỗi người trong số các loại cần phải có phương pháp tĩnh trước khi suy nghĩ thêm nữa ..

Tại sao không tạo lớp utlity bằng các phương thức tĩnh mà chúng cần chia sẻ? (Ví dụ ClassHelper.RetrieveByID(string id) hoặc ClassHelper<ClassA>.RetrieveByID(string id)

Theo kinh nghiệm của tôi với những loại "rào chắn" vấn đề không phải là những hạn chế của ngôn ngữ, nhưng những hạn chế của thiết kế của tôi ..

2

như thế nào ObjectA và AHelper liên quan? Is AHelper.RetrieveByID() logic giống như BHelper.RetrieveByID()

Nếu có, làm thế nào về một cách tiếp cận lớp Utility dựa (lớp học với phương pháp tĩnh công cộng duy nhất và không một quốc gia)

static [return type] Helper.RetrieveByID(ObjectX x) 
0

làm thế nào để gửi phản hồi về Stack Overflow? Chỉnh sửa bài đăng gốc của tôi hoặc đăng "câu trả lời"? Dù sao, tôi nghĩ rằng nó có thể giúp đỡ để cho một ví dụ về những gì đang xảy ra trong AHelper.RetrieveByID() và BHelper.RetreiveByID()

Về cơ bản, cả hai phương pháp này đều đi ngược lại với dịch vụ web của bên thứ ba. đối tượng generic (castable) bằng cách sử dụng một phương thức Query nhận trong một chuỗi giả SQL như là các tham số duy nhất của nó.

Vì vậy, AHelper.RetrieveByID (string ID) có thể trông như

 
public static AObject RetrieveByID(string ID) 
{ 
    QueryResult qr = webservice.query("SELECT Id,Name FROM AObject WHERE Id = '" + ID + "'"); 

    return (AObject)qr.records[0]; 
} 

public static BObject RetrieveByID(string ID) 
{ 
    QueryResult qr = webservice.query("SELECT Id,Name,Company FROM BObject WHERE Id = '" + ID + "'"); 

    return (BObject)qr.records[0]; 
} 

Hy vọng rằng sẽ giúp. Như bạn có thể thấy, hai phương thức tương tự nhau, nhưng truy vấn có thể hơi khác một chút dựa trên kiểu đối tượng khác được trả về.

Ồ, và Rob, tôi hoàn toàn đồng ý - điều này có nhiều khả năng là một hạn chế trong thiết kế của tôi chứ không phải ngôn ngữ.:)

0

Bạn đang tìm kiếm hành vi đa hình? Sau đó, bạn sẽ muốn giao diện và hàm tạo thông thường. Điều gì là không trực quan về việc gọi một nhà xây dựng? Nếu bạn không cần đa hình (âm thanh như bạn không sử dụng nó bây giờ), sau đó bạn có thể gắn bó với các phương pháp tĩnh của bạn. Nếu đây là tất cả các trình bao bọc xung quanh một thành phần của nhà cung cấp, thì có lẽ bạn có thể thử sử dụng một phương thức factory để tạo chúng như VendorBuilder.GetVendorThing ("A") có thể trả về một đối tượng kiểu IVendorWrapper.

2

Bạn không thể quá tải phương thức bằng cách thay đổi kiểu trả về.

Bạn có thể sử dụng tên gọi khác nhau:

static AObject GetAObject(string id); 
static BObject GetBObject(string id); 

Hoặc bạn có thể tạo một lớp học với các nhà khai thác đúc:

class AOrBObject 
{ 
    string id; 
    AOrBObject(string id) {this.id = id;} 

    static public AOrBObject RetrieveByID(string id) 
    { 
     return new AOrBObject(id); 
    } 

    public static AObject explicit operator(AOrBObject ab) 
    { 
     return AObjectQuery(ab.id); 
    } 

    public static BObject explicit operator(AOrBObject ab) 
    { 
     return BObjectQuery(ab.id); 
    } 
} 

Sau đó, bạn có thể gọi nó như vậy:

var a = (AObject) AOrBObject.RetrieveByID(5); 
var b = (BObject) AOrBObject.RetrieveByID(5); 
3

Đối với một giải pháp tổng quát để dụ, bạn có thể làm điều này:

public static T RetrieveByID<T>(string ID) 
{ 
    var fieldNames = getFieldNamesBasedOnType(typeof(T)); 
    QueryResult qr = webservice.query("SELECT "+fieldNames + " FROM " 
            + tyepof(T).Name 
            +" WHERE Id = '" + ID + "'"); 
    return (T) qr.records[0]; 
} 
+0

+1.Tôi làm điều này trong một số truy vấn libs, đặc biệt là những cái mà chảy qua các dịch vụ web. – jro

5

Nếu Tôi đã được bạn tôi sẽ cố gắng tránh bất kỳ statics. IMHO Tôi luôn luôn kết thúc với một số loại vấn đề đồng bộ hóa xuống đường với statics. Điều đó đang được nói rằng bạn đang trình bày một ví dụ điển hình về lập trình chung bằng cách sử dụng các mẫu. Tôi sẽ áp dụng giải pháp dựa trên mẫu của Rob Copper được trình bày ở một trong các bài viết trên.

0

marxidad Chỉ cần lưu ý nhanh, Justin đã nói rằng SQL thay đổi phụ thuộc rất nhiều vào loại, vì vậy tôi đã làm việc trên cơ sở rằng nó có thể là một điều gì đó khác, do đó ủy quyền nó cho các lớp con đang được đề cập đến. Trong khi giải pháp của bạn kết hợp SQL VERY chặt chẽ với Loại (tức là SQL).

rptony Tốt điểm về các vấn đề đồng bộ hóa có thể với tĩnh học, một tôi không đề cập đến, vì vậy cảm ơn bạn :) Ngoài ra, Rob nó Cooper (không đồng) BTW;): D (EDIT: Chỉ cần nghĩ tôi sẽ đề cập rằng trong trường hợp nó không phải là một lỗi đánh máy, tôi mong đợi nó là, do đó, không có vấn đề!)

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