2

我的控制器继承自一个包含实现 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) {
    }

所以我想我会把我的代码放在第二种方法中。不确定这种行为是否是合同规定的。

4

3 回答 3

0

ASP.NET MVC 中的控制器类已正确实现 IDisposable 接口。如需进一步参考,请在 MSDN 页面上查看此页面,该页面准确指定了这一点。

要插入 IDisposible 接口,您需要覆盖您想出的受保护的 dispose 方法,并将逻辑放置在那里“您自己的”类。

于 2012-05-24T04:32:30.573 回答
0

如果IDisposable.Dispose使用非密封方法实现,则派生类型的代码将在基本类型清理代码之前和之后运行;因为GC.SuppressFinalize不应该在派生类型完成其清理之后调用(包括可能在基类型完成清理之后发生的任何部分),所以GC.SuppressFinalize在密封实现中进行,该实现又调用其签名为的虚拟方法void Dispose(bool).

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

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

早在 Microsoft 想出处理非托管资源的最佳方法之前,该Dispose模式就是一个很好的初步尝试。今天,我认为最好将虚拟方法的参数视为用于更改签名的虚拟参数,而不是有意义的东西(即使True从包装器链接虚拟方法时应该始终传递)。

于 2012-05-24T15:15:45.533 回答
-1

1)在您当前的类上实现可丢弃的接口并做您想做的事情 2)在您的基类中实现该接口,然后在此类中覆盖它 3)仅在您的基类中实现该接口并且不要覆盖另外,你的代码看起来很奇怪,你有一个抽象类,你提供了实现逻辑

于 2012-05-24T04:35:10.637 回答