2010-01-05 43 views
6

我有一個簡單的問題。用C包裝非繼承類#

我想裝飾SqlDataReader類,以便當調用dispose或close方法時,我可以同時處置隱藏的資源。

SqlDataReader類不可繼承。

我該如何做到這一點?我真的不想實現DbDataReader,IDataReader,IDisposable & IDataRecord接口

+0

你是什麼意思,不可繼承?這是密封的班嗎?你會詳細說明接口嗎?你不需要執行這些嗎?另外,你爲什麼不想要? – 2010-01-05 04:12:20

+0

SqlDataReader不是密封的,所以它是可繼承的,但它的構造函數是私有的,所以當你從它繼承時你不能滿足基礎構造函數 - 我只是挑剔細節,但是,你是對的。 – 2010-01-05 04:19:55

+0

除了我對silky的回答的評論之外,我不禁想知道......你可能需要用「SqlDataReader」打包什麼?我真的希望它不是'SqlCommand'或'SqlConnection' ... – Aaronaught 2010-01-05 04:35:47

回答

5

即使您可以從SqlDataReader繼承,反正也無所謂,因爲您無法使SqlCommand創建派生類的實例。

在包裝器中實現IDataReader實際上並不難,當你只是推遲到底層的SqlDataReader。這只是一點點時間,但並不那麼糟糕。

但我很好奇,是你想要處理的資源嗎?如果是這樣,則CommandBehavior枚舉的CloseConnection成員可以確保在數據閱讀器關閉時連接將被關閉。

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

請注意,Close/Dispose在SqlDataReader上是一樣的。

最後,這裏有個最後的建議,它在過去很好。請注意,在以下鬆散示例中,即使您在每條記錄的「調用者」處「返回」,也會從頭到尾擁有SqlDataReader。

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

該資源是一次性票據,用於防止訪問SQL數據庫 – 2010-01-05 04:47:14

+0

好的,我在我的答案中增加了另一個建議,可能有所幫助。 – Josh 2010-01-05 04:49:17

+0

這是一個非常有趣的解決方案。 這是什麼人的想法? – 2010-01-05 05:02:38

3

反轉它;使用您的「隱藏」資源作爲主要工具,實現IDisposable,然後在完成後關閉DataReader。

+0

我真的寧願調用代碼不知道任何事情。它目前正在期待SqlDataReader的一個實例 – 2010-01-05 04:19:37

+4

你是否擁有調用代碼?它真的需要接受一個'SqlDataReader'嗎?這是你應該儘量不要傳遞的東西;如果你可以讓它接受'IDataReader',那麼你可以很容易地包裝'SqlDataReader'。 – Aaronaught 2010-01-05 04:34:40

+0

是的,我擁有調用代碼。我寧願不必包裝類(實現IDataReader) – 2010-01-05 04:48:38

1

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.aspx 該類是不密封的。您應該能夠在覆蓋開始時調用base.dispose(),然後將代碼放在後面。

我沒有我在我的面前,但是IDE它看起來應該像財產以後

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. 
    } 
} 

編輯--- 剛纔讀的原單的評論,我看到它有私有的構造函數,讓我爆發我的VS2008和虐待BRB

尋找到它,每個人都試圖這些花哨的解決方案,我認爲是可以做的唯一事情就是

public class myClass : IDisposable 
{ 

    public SqlDataReader dataReader { get; set; } 

    #region IDisposable Members 

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

    #endregion 
} 

編輯---嘆了一口氣,這是興奮的絲柔發佈了40分鐘前。

+0

此代碼導致編譯錯誤:錯誤#1類型'System.Data.SqlClient.SqlDataReader'沒有構造函數定義...和...錯誤#2 'System.Data.SqlClient.SqlDataReader.SqlDataReader(System.Data.SqlClient.SqlCommand,System.Data.CommandBehavior)'由於其保護級別不可訪問 – 2010-01-05 04:32:25

+0

您的鏈接的第一行:「此類不能被繼承。」 – kristian 2010-01-05 04:33:06

+0

不妨傳回一個 2010-01-05 04:53:39