C# “我怎么能?”;连锁店;可识别对象
我使用常规的C# “我怎么能?”;连锁店;可识别对象,c#,idisposable,C#,Idisposable,我使用常规的Sql*对象来查询我的数据库: // conn is a SqlConnection // transaction is a SqlTransaction using(var cmd = new SqlCommand(someSelectQuery, conn, transaction)) using(var reader = cmd.ExecuteReader()) { ... } 我将编写一个包装器,它将newsqlcomman
Sql*
对象来查询我的数据库:
// conn is a SqlConnection
// transaction is a SqlTransaction
using(var cmd = new SqlCommand(someSelectQuery, conn, transaction))
using(var reader = cmd.ExecuteReader())
{
...
}
我将编写一个包装器,它将newsqlcommand()
和cmd.ExecuteReader()
打包在一起:
using(var someNewReader = GetSelectReader(someSelectQuery, conn, transaction))
{
...
}
问题是:这个“someNewReader”对象(或struct?)应该:
SqlDataReader
.Dispose()
方法,该方法同时处理底层的SqlCommand
和SqlDataReader
我尝试的 我尝试创建一个包装类,它包含两个字段,一个
SqlCommand
和一个SqlDataReader
,以及:
SqlDataReader的方法
.Dispose()
方法(按正确顺序)以正确的方式重新实现
.Dispose()
(特别是:以正确的方式处理异常,并且仍然尝试.Dispose()
每个人)会增加容易出错的编码开销,但每个.Dispose()
链都会遵循准确的smae结构
问题
我想知道是否有一种机制可以将几个IDisposable
对象“链接在一起”,这可以让我描述:
- 输入:
是obj
一次性的
- 输入:
是parent
一次性的
- 输出仍然有一个
(至少具有相同的公共接口),但它正确地调用obj
,然后在Dispose时调用obj.Dispose()
parent.Dispose()
class DisposableTupleContainer<D1, D2>: IDisposable
where D1 : IDisposable
where D2 : IDisposable
{
private bool _disposed = false;
private (D1, D2) _items;
public D1 Item1 => _disposed ? throw new ObjectDisposedException("d1") : _items.Item1;
public D2 Item2 => _disposed ? throw new ObjectDisposedException("d2") : _items.Item2;
public DisposableTupleContainer(D1 d1, Func<D1,D2> d2)
// add try catch to destroy d1 if d2() throws and exception
=> _items = (d1, d2(d1));
public void Dispose()
{
if (!_disposed)
{
// dispose d1, d2, handle exception
_disposed = true;
}
}
}
此选项提供了强大的键入功能。这和你现在的情况很相似。我不认为它非常优雅:但是,用工厂方法或只是嵌套<代码>使用< /代码>看起来更为常见。
请注意,C#8包含一些使用的,现在您可以在声明中指定它:
using var cmd = new SqlCommand(someSelectQuery, conn, transaction);
using var reader = cmd.ExecuteReader();
在正确的maner中重新实现.Dispose()会增加容易出错的编码开销
-当您告诉VS在您的对象上实现IDisposable
时,只需让它为您生成样板文件,然后填充空白即可。仔细检查您的选择是否符合要求。在你的例子中,如果你的类是密封的,它是第一个选项,如果不是,它是没有终结器的第二个选项。作为旁注,有些东西不需要你处理它们,就像它们被传递到一个对象中一样,对象负责处理它们。这通常发生在传递streams etcI将生成两个方法并将execute reader调用作为委托推送到另一个(处理命令和连接)时。它为您提供了所需的方法,但不能“链接IDisposable”。
using var cmd = new SqlCommand(someSelectQuery, conn, transaction);
using var reader = cmd.ExecuteReader();