2010-01-05 33 views
6

Tôi có một vấn đề đơn giản.Bao gồm một lớp không thể kế thừa trong C#

Tôi muốn trang trí lớp SqlDataReader để khi các phương pháp bỏ hoặc đóng được gọi là tôi có thể vứt bỏ một tài nguyên ẩn cùng một lúc.

lớp SqlDataReader không thể kế thừa.

Tôi làm cách nào để thực hiện việc này? Tôi thực sự không muốn triển khai DbDataReader, IDataReader, IDisposable & Giao diện IDataRecord

+0

Ý của bạn là gì không thể kế thừa? Nó là một lớp niêm phong? Bạn sẽ xây dựng trên các giao diện? Bạn không phải thực hiện chúng? Ngoài ra, tại sao bạn không muốn? –

+0

SqlDataReader không được niêm phong vì vậy nó có thể kế thừa, nhưng các nhà xây dựng của nó là riêng tư, do đó bạn không thể đáp ứng được hàm tạo cơ sở khi bạn kế thừa từ nó - tôi chỉ cần nitpicking chi tiết nhưng bạn vẫn đúng. –

+0

Ngoài nhận xét của tôi về câu trả lời của silky, tôi không thể không tự hỏi ... những gì bạn có thể cần phải đóng gói với một 'SqlDataReader'? Tôi thực sự hy vọng nó không phải là một 'SqlCommand' hoặc' SqlConnection' ... – Aaronaught

Trả lời

5

Thậm chí nếu bạn có thể kế thừa từ SqlDataReader nó sẽ không quan trọng anyway bởi vì bạn không thể làm cho SqlCommand tạo một thể hiện của lớp dẫn xuất của bạn.

Triển khai IDataReader trong trình bao bọc thực sự không khó chút nào khi bạn chỉ trì hoãn SqlDataReader cơ bản. Đó chỉ là một chút thời gian nhưng không phải là xấu.

Nhưng tôi tò mò, là tài nguyên bạn muốn xử lý kết nối? Nếu vậy có một thành viên CloseConnection của CommandBehavior enum đảm bảo kết nối sẽ bị đóng khi trình đọc dữ liệu bị đóng.

var reader = command.ExecuteReader(CommandBehavior.CloseConnection); 
... 
reader.Close(); // also closes connection 

Lưu ý rằng Đóng/Xử lý giống nhau trên SqlDataReader.

Cuối cùng, đây là một đề xuất cuối cùng đã phục vụ tôi tốt trong quá khứ. Lưu ý rằng trong ví dụ lỏng lẻo sau đây, bạn sở hữu SqlDataReader từ đầu đến cuối ngay cả khi bạn "đang sinh" trở lại người gọi tại mỗi bản ghi.

private static IEnumerable<IDataRecord> GetResults(this SqlCommand command) { 
    using (var myTicket = new MyTicket()) 
    using (var reader = command.ExecuteReader()) { 
     while (reader.Read()) { 
      yield return reader; 
     } 
    } 
    // the two resources in the using blocks above will be 
    // disposed when the foreach loop below exits 
} 

... 

foreach (var record in myCommand.GetResults()) { 

    Console.WriteLine(record.GetString(0)); 

} 

// when the foreach loop above completes, the compiler-generated 
// iterator is disposed, allowing the using blocks inside the 
// above method to clean up the reader/myTicket objects 
+0

Tài nguyên là một vé dùng một lần đang được sử dụng để bảo vệ quyền truy cập vào Cơ sở dữ liệu SQL –

+0

Được rồi, tôi đã thêm một đề xuất khác trong câu trả lời của tôi có thể hữu ích. – Josh

+0

Đó là một giải pháp rất thú vị. Suy nghĩ của mọi người về điều này là gì? –

3

Đảo ngược nó; sử dụng tài nguyên "Ẩn" của bạn làm điều chính, triển khai IDisposable và sau đó đóng DataReader khi bạn đã hoàn thành nó.

+0

Tôi thực sự thay vì mã gọi điện thoại không biết gì về nó. Nó hiện đang mong đợi một thể hiện của SqlDataReader –

+4

Bạn có sở hữu mã gọi không? Liệu nó thực sự cần phải chấp nhận một 'SqlDataReader'? Đó là điều bạn nên cố gắng không vượt qua; nếu bạn có thể làm cho nó chấp nhận một 'IDataReader' thay vào đó bạn có thể quấn' SqlDataReader' khá dễ dàng. – Aaronaught

+0

Có Tôi sở hữu mã gọi điện. Tôi không muốn quấn lớp (thực hiện IDataReader) –

1

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.aspx Lớp học không được niêm phong. Bạn chỉ có thể gọi base.dispose() khi bắt đầu ghi đè và sau đó đặt mã của bạn sau đó.

Tôi không có IDE của tôi trước mặt tôi nhưng nó sẽ giống somthing như

public myClass : SqlDataReader 
{ 
    protected overide void Dispose(bool disposing) : Base(disposing) 
    { 
     myCleanupCode(); 
    } 
    protected overide void Dispose() 
    { 
     myCleanupCode(); 
    } 
    private myCleanupCode() 
    { 
     //Do cleanup here so you can make one change that will apply to both cases. 
    } 
} 

EDIT --- chỉ đọc những ý kiến ​​ban đầu, tôi thấy rằng nó có xây dựng tư nhân, hãy để tôi thoát ra khỏi VS2008 của tôi và bệnh BRB

nhìn vào nó, và tất cả mọi người đang cố gắng những giải pháp ưa thích, điều duy nhất tôi thấy rằng có thể thực hiện là

public class myClass : IDisposable 
{ 

    public SqlDataReader dataReader { get; set; } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     dataReader.Dispose(); 
     //My dispose code 
    } 

    #endregion 
} 

EDIT --- Sigh, đây là excatly những gì mượt được đăng 40 phút trước đây.

+0

Mã này gây ra các L COMPI COMPILE: Lỗi # 1 Kiểu 'System.Data.SqlClient.SqlDataReader' không có hàm tạo nào được định nghĩa ... và ... Lỗi # 2 'System.Data.SqlClient.SqlDataReader.SqlDataReader (System.Data.SqlClient.SqlCommand, System.Data.CommandBehavior)' là không thể truy cập do mức bảo vệ của nó –

+0

dòng đầu tiên của liên kết của bạn: "Lớp này không thể được kế thừa." – kristian

+0

Cũng có thể trả lại một Tuple của

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