简体   繁体   English

当我的控制器的字段实现IDisposable时,该如何处置?

[英]How do I dispose of my Controllers when their fields implement IDisposable?

My Controllers inherit from a class that contains a field that implements IDisposable. 我的控制器从一个类中继承,该类包含一个实现IDisposable的字段。 So my first instinct was to write: 所以我的第一个直觉是写:

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();
        }
    }
}

but this won't compile because Controller does not mark the Dispose method as virtual/override. 但这不会编译,因为Controller不会将Dispose方法标记为virtual / override。 So now I think I'm stuck. 所以现在我觉得我被困住了。 Even if I mark my method as new, won't the framework hold references typed as Controller and as such my method will never be invoked? 即使我将我的方法标记为新方法,框架也不会保留键入为Controller的引用,因此永远不会调用我的方法吗? Suggestions on how to work around this? 有关如何解决此问题的建议?

UPDATE 更新

So I looked at the MVC3 source and saw this: 因此,我查看了MVC3源,并看到了以下内容:

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

    protected virtual void Dispose(bool disposing) {
    }

So I guess I'll just put my code in the 2nd method. 所以我想我将代码放入第二种方法中。 Not sure that this behavior is contractually specified though. 但是,不能确定是否通过合同指定了此行为。

The controller class in ASP.NET MVC has correctly implemented IDisposable interface. ASP.NET MVC中的控制器类已正确实现IDisposable接口。 For further reference, check this page on MSDN page that exactly specifies this. 有关更多参考,请在MSDN页面上检查页面,以准确指定此内容。

To plug into the IDisposible interface, you need to override the protected dispose method that you have figured out and put the logic to dispose "your own" class there. 要插入IDisposible接口,您需要覆盖已经弄清楚的受保护的dispose方法,并在其中放置逻辑以处理“您自己的”类。

If IDisposable.Dispose were implemented with an unsealed method, then the code for derived types would run before and after the base-type cleanup code; 如果IDisposable.Dispose是用未密封的方法实现的,则派生类型的代码将在基本类型清除代码之前和之后运行; since GC.SuppressFinalize shouldn't be called until after a derived type has finished its cleanup (including any portions that should perhaps occur after the base type has finished its cleanup), the GC.SuppressFinalize is made in a sealed implementation which in turn calls a virtual method whose signature is void Dispose(bool) . 因为GC.SuppressFinalize不应该被调用,直到派生类型已完成后其清理(包括应基类型之后也许发生的任何部分已完成其清理),则GC.SuppressFinalize在密封方面取得这又呼叫一个虚拟方法,其签名为void Dispose(bool)

Note that while conceptually it is a good idea to have a virtual method called within a sealed wrapper, there are some flaws in Microsoft's implementation. 请注意,虽然从概念上讲,在密封包装中调用虚拟方法是一个好主意,但Microsoft的实现存在一些缺陷。 Most notably: 最为显着地:

  1. Because it uses a private flag in the base class indicate whether the object has yet been disposed, but does not use that flag in the wrapper method, every derived class that wishes to avoid duplicate disposal must also have its own disposal flag; 因为它在基类中使用一个私有标志来指示对象是否已经被处置,但是在包装方法中不使用该标志,所以每个希望避免重复处置的派生类也必须具有自己的处置标志;
  2. There are three scenarios by which a derived `Dispose` call could exit: 在三种情况下,派生的“ Dispose”调用可以退出:
    1. It could return normally 它可以正常返回
    2. It could throw an exception, but nonetheless have achieved everything that can be achieved such that finalization should nonetheless be suppressed (eg because an `IDisposable` logging object wrapped a file, and the file data was not written successfully on closure). 它可能会引发异常,但是尽管如此,它已经实现了可以实现的所有目标,因此仍然应抑制最终确定(例如,因为“ IDisposable”日志记录对象包装了文件,并且文件数据在关闭时未成功写入)。 An ugly situation, but one which isn't helped by leaving the object registered for finalization. 这是一个丑陋的情况,但是通过将对象注册为最终确定却无济于事。
    3. It could throw an exception, in a scenario where the object should remain eligible for finalization. 在对象应保持合格的情况下,可能会引发异常。
    Microsoft's `Dispose` pattern provides no means of distinguishing among the latter two choices. 微软的“ Dispose”模式无法区分后两种选择。 While leaving an object registered for finalization-based cleanup might in many cases be harmless, it could cause confusion if the `Finalize` method is used to log failures to call `Dispose`. 尽管将对象注册为进行基于终结的清理可能在许多情况下是无害的,但是如果使用“ Finalize”方法记录失败以调用“ Dispose”,则可能引起混乱。
  3. It implies that objects should often hold some resources that they clean up via finalization and some resources that are only cleaned up via `Dispose`, and that unsealed types which don't clean up anything via finalization should make provision for derived types which might. 这意味着对象通常应该拥有一些通过终结处理清理的资源和一些仅通过`Dispose'清理的资源,并且那些未通过终结处理清理任何内容的未密封类型应该为可能的派生类型做好准备。 In practice, classes with finalizers should avoid holding references to any objects not needed for finalization; 实际上,带有终结器的类应避免持有对终结器不需要的任何对象的引用。 resources which need finalization should be encapsulated into their own class objects, which should then be held by classes that wouldn't have to worry about finalizing them. 需要终结的资源应该封装到自己的类对象中,然后由不必担心终结的类所拥有。

Back before Microsoft had figured out the best ways to handle unmanaged resources, the Dispose pattern was a good first effort. 在Microsoft找出处理非托管资源的最佳方法之前, Dispose模式是很好的第一步。 Today, I would think it better to regard the virtual method's parameter as being a dummy parameter used to change the signature, than as something meaningful (even though one should always pass True when chaining the virtual method from the wrapper). 今天,我认为将虚拟方法的参数视为用于更改签名的伪参数比将其视为有意义的东西更好(即使从包装程序链接虚拟方法时始终应通过True )。

1)在您当前的类上实现该接口,并执行您想做的事情2)在您的基类中实现该接口,然后在该类中对其进行覆盖3)仅在您的基类中实现该接口,并且不要覆盖您的代码看起来很奇怪,您有一个抽象类,并且提供了实现逻辑

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM