在C#中包装一个不可继承的类

时间:2010-01-05 04:10:22

标签: c#

我有一个简单的问题。

我想装饰SqlDataReader类,这样当调用dispose或close方法时,我可以同时处理一个隐藏的资源。

SqlDataReader类不可继承。

我怎样才能做到这一点?我真的不想实现DbDataReader,IDataReader,IDisposable& IDataRecord接口

3 个答案:

答案 0 :(得分:5)

即使您可以从SqlDataReader继承也无关紧要,因为您无法使SqlCommand创建派生类的实例。

当你刚刚推迟到底层的SqlDataReader时,在包装器中实现IDataReader实际上并不难。这只是耗费一点时间,但并不是那么糟糕。

但我很好奇,你想要的资源是否已经解决了连接问题?如果是这样,CommandBehavior枚举的CloseConnection成员将确保在数据读取器关闭时关闭连接。

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

请注意,SqlDataReader上的Close / Dispose是相同的。

最后,这是最后一个在过去很好用的建议。请注意,在下面的松散示例中,您从头到尾拥有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

答案 1 :(得分:3)

扭转它;使用“隐藏”资源作为主要内容,实现IDisposable,然后在完成后关闭DataReader。

答案 2 :(得分: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.
    }
}

<击> EDIT --- 只是阅读原始评论,我看到它有私人构造函数,让我打破我的VS2008和病态

看着它,每个人都在尝试这些奇特的解决方案,我唯一能看到的就是

public class myClass : IDisposable
{

    public SqlDataReader dataReader { get; set; }

    #region IDisposable Members

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

    #endregion
}

编辑---叹了口气,这真是40分钟前Silky发布的。