我有一個簡單的問題。用C包裝非繼承類#
我想裝飾SqlDataReader類,以便當調用dispose或close方法時,我可以同時處置隱藏的資源。
SqlDataReader類不可繼承。
我該如何做到這一點?我真的不想實現DbDataReader,IDataReader,IDisposable & IDataRecord接口
我有一個簡單的問題。用C包裝非繼承類#
我想裝飾SqlDataReader類,以便當調用dispose或close方法時,我可以同時處置隱藏的資源。
SqlDataReader類不可繼承。
我該如何做到這一點?我真的不想實現DbDataReader,IDataReader,IDisposable & IDataRecord接口
即使您可以從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
該資源是一次性票據,用於防止訪問SQL數據庫 – 2010-01-05 04:47:14
好的,我在我的答案中增加了另一個建議,可能有所幫助。 – Josh 2010-01-05 04:49:17
這是一個非常有趣的解決方案。 這是什麼人的想法? – 2010-01-05 05:02:38
反轉它;使用您的「隱藏」資源作爲主要工具,實現IDisposable,然後在完成後關閉DataReader。
我真的寧願調用代碼不知道任何事情。它目前正在期待SqlDataReader的一個實例 – 2010-01-05 04:19:37
你是否擁有調用代碼?它真的需要接受一個'SqlDataReader'嗎?這是你應該儘量不要傳遞的東西;如果你可以讓它接受'IDataReader',那麼你可以很容易地包裝'SqlDataReader'。 – Aaronaught 2010-01-05 04:34:40
是的,我擁有調用代碼。我寧願不必包裝類(實現IDataReader) – 2010-01-05 04:48:38
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分鐘前。
此代碼導致編譯錯誤:錯誤#1類型'System.Data.SqlClient.SqlDataReader'沒有構造函數定義...和...錯誤#2 'System.Data.SqlClient.SqlDataReader.SqlDataReader(System.Data.SqlClient.SqlCommand,System.Data.CommandBehavior)'由於其保護級別不可訪問 – 2010-01-05 04:32:25
您的鏈接的第一行:「此類不能被繼承。」 – kristian 2010-01-05 04:33:06
不妨傳回一個
你是什麼意思,不可繼承?這是密封的班嗎?你會詳細說明接口嗎?你不需要執行這些嗎?另外,你爲什麼不想要? – 2010-01-05 04:12:20
SqlDataReader不是密封的,所以它是可繼承的,但它的構造函數是私有的,所以當你從它繼承時你不能滿足基礎構造函數 - 我只是挑剔細節,但是,你是對的。 – 2010-01-05 04:19:55
除了我對silky的回答的評論之外,我不禁想知道......你可能需要用「SqlDataReader」打包什麼?我真的希望它不是'SqlCommand'或'SqlConnection' ... – Aaronaught 2010-01-05 04:35:47