当字段实现IDisposable时,如何处理控制器?

时间:2012-05-24 04:14:33

标签: c# asp.net-mvc asp.net-mvc-3 model-view-controller idisposable

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

所以我猜我只是把我的代码放在第二种方法中。不确定此行为是否按合同规定。

3 个答案:

答案 0 :(得分:0)

ASP.NET MVC中的控制器类已正确实现IDisposable接口。有关进一步参考,请在MSDN页面上检查this page,确切地指定此内容。

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

答案 1 :(得分:0)

如果使用未密封的方法实现IDisposable.Dispose,则派生类型的代码将在基本类型清理代码之前和之后运行;因为GC.SuppressFinalize直到派生类型完成清理后才会被调用(包括在基类型完成清理后可能发生的任何部分),GC.SuppressFinalize是在密封的实现中生成的然后调用签名为void Dispose(bool)的虚拟方法。

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

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

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

答案 2 :(得分:-1)

1)在当前类上实现idisposable接口并执行您想要执行的操作 2)在基类中实现该接口,然后在此类中覆盖它 3)只在基类中实现该接口,不要覆盖  此外,您的代码看起来很奇怪,您有一个抽象类,并提供实现逻辑