gpt4 book ai didi

c# - 当它们的字段实现 IDisposable 时,我该如何处理我的 Controller ?

转载 作者:太空宇宙 更新时间:2023-11-03 17:03:59 26 4
gpt4 key购买 nike

我的 Controller 继承自一个包含实现 IDisposable 的字段的类。所以我的第一直觉是写:

public abstract class EventRepositoryControllerBase : Controller
{
protected EventRepository eventRepos { get; private set; }

public EventRepositoryControllerBase(EventRepository eventRepos)
{
this.eventRepos = eventRepos;
}

public override void Dispose()
{
try
{
base.Dispose();
}
finally
{
eventRepos.Dispose();
}
}
}

但这不会编译,因为 Controller 没有将 Dispose 方法标记为虚拟/覆盖。所以现在我想我被困住了。即使我将我的方法标记为新方法,框架不会保留类型为 Controller 的引用,因此我的方法永远不会被调用吗?有关如何解决此问题的建议?

更新

所以我查看了 MVC3 源代码并看到了这个:

 public void Dispose() {
Dispose(true /* disposing */);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing) {
}

所以我想我会把我的代码放在第二种方法中。但不确定此行为是否在契约(Contract)中指定。

最佳答案

如果 IDisposable.Dispose 是用未密封的方法实现的,那么派生类型的代码将在基类型清理代码之前和之后运行;由于 GC.SuppressFinalize 在派生类型完成清理之前不应调用(包括在基类型完成清理后可能发生的任何部分),GC.SuppressFinalize 是在一个密封的实现中进行的,该实现依次调用一个签名为 void Dispose(bool) 的虚方法。

请注意,虽然从概念上讲,在密封包装器中调用虚拟方法是个好主意,但 Microsoft 的实现存在一些缺陷。最值得注意的是:

  1. 因为它在基类中使用了一个私有(private)标志来指示对象是否已经被释放,但是在包装方法中没有使用该标志,所以每个希望避免重复释放的派生类也必须有自己的释放标志;
  2. 派生的 `Dispose` 调用可以在三种情况下退出:
    1. 可以正常返回
    2. 它可能会抛出一个异常,但仍然实现了所有可以实现的东西,因此最终应该被抑制(例如,因为 `IDisposable` 日志对象包装了一个文件,并且文件数据没有成功写入在关闭)。一个丑陋的情况,但是通过将对象注册为最终确定并没有帮助。
    3. 在对象应保持有资格完成的情况下,它可能会引发异常。
    Microsoft 的“Dispose”模式无法区分后两种选择。虽然在许多情况下让对象注册为基于终结的清理可能是无害的,但如果使用 Finalize 方法记录调用 Dispose 的失败,则可能会引起混淆。
  3. 这意味着对象应该经常持有一些它们通过终结清理的资源和一些只通过 `Dispose` 清理的资源,并且不通过终结清理任何东西的未密封类型应该使提供可能的派生类型。实际上,带有终结器的类应该避免持有对终结不需要的任何对象的引用;需要终结的资源应该封装到它们自己的类对象中,然后这些对象应该由不必担心终结它们的类持有。

在 Microsoft 找出处理非托管资源的最佳方法之前,Dispose 模式是一个很好的尝试。今天,我认为最好将虚拟方法的参数视为用于更改签名的虚拟参数,而不是有意义的东西(即使在将虚拟方法从包装器)。

关于c# - 当它们的字段实现 IDisposable 时,我该如何处理我的 Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10731054/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com