本文介绍了对象需要以特定的顺序排列:这是一个代码的味道?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文

The context

我正在使用Winforms应用程序(.NET 3.5 SP1),它具有工作空间的概念,可以包含n个面板。每个面板(派生自面板)具有视图:

I'm working with a Winforms application (.NET 3.5 SP1) which has the concept of workspaces, which can contain n number of panels. Each panel (derives from Panel) has view:


    .-----------------------.
    |Workspace              |
    |.--------.  .--------. |
    ||Panel1  |  |Panel2  | |
    ||.-----. |  |.-----. | |
    |||View1| |  ||View2| | |
    ||'-----' |  |'-----' | |
    |'--------'  '--------' |
    '-----------------------'

所有面板都将添加到Workspace类的 this.Controls 集合中(源自 UltraTabPageControl ,Infragistics GUI控件)。每个视图都添加到其父代的 Controls 集合中。因此,当在工作区上调用 Dispose 时,面板和视图会自动被处理,这是完全预期和期望的。

All panels get added to the this.Controls collection of the Workspace class (which derives from an UltraTabPageControl, an Infragistics GUI control). Each view is added to the Controls collection of their parent. So, when Dispose is called on the Workspace, the panels and views automatically get disposed, which is completely expected and desired.

我们有另一个概念称为 ViewManager 。它跟踪工作区中的所有 View 控件,并负责维护单个主视图。无论何时创建 View ,它将向该管理员注册。这将把 View 添加到列表中,然后运行一些逻辑来确定新的主视图,然后调用一个 Synchronize()方法。

We have another concept called a ViewManager. It keeps track of all the View controls in the workspace, and is in charge of maintaining a single "master" view. Whenever a View is created, it registers itself with this manager. This adds the View to a list, and then runs some logic to determine the new "master" view and then calls a Synchronize() method on each View.

目前的设计是,每当 View.Dispose()被调用,它从 ViewManager 中注销自己。这将从列表中删除 View ,然后运行相应的逻辑,检查其他视图中的新主。

The current design is that, whenever View.Dispose() is called, it unregisters itself from the ViewManager. This removes the View from the list, and then runs corresponding logic that checks for a new master, out of the remaining views.

扭曲

The twist

当我们关闭整个工作区时,有一个特殊的面板类型需要在其他面板之前关闭。所以我们在 Dispose 方法中的代码如下所示:

When we are closing an entire workspace, there is one special Panel type that needs to be closed before other panels. So we have code in our Dispose method that looks like this:

protected override void Dispose(bool disposing)
{
    var theSpecialPanel = GetSpecialPanel();
    if (theSpecialPanel != null)
    {
        theSpecialPanel.Dispose();
    }
    base.Dispose(disposing);
}

如果我们取出该代码,那么其他面板可能会在 theSpecialPanel 。这将导致检查新主控面板的运行逻辑,在每个查看上调用 Synchronize()专门面板这将抛出一个

If we take out that code, then other panels may be disposed before theSpecialPanel. This causes the logic that checks for a new master panel to be run, calls Synchronize() on each View including this special panel. This throws an

InvalidComObjectException:与其底层RCW分离的COM对象无法使用。

"InvalidComObjectException: COM object that has been separated from its underlying RCW cannot be used."

问题

这个设计是否是一个代码气味?执行某个特定对象在其他人之前被处理是很奇怪的吗?

Is this design is a code smell? Is it strange to enforce that a specific object gets disposed before others?

推荐答案

在代码片段中,我没有看到你正在处理其他面板。

In your code snippet, I didn't see where you're disposing of the other panels.

如果处理所有面板,我没有看到任何问题,决定任何处理的顺序。如果我正确地跟着你,你可以这样做:

If you dispose of all panels, I don't see any problem with deciding on any order of disposal that you wish. If I've followed you correctly, you can do:

foreach (panel in Panels.Where(p => p != theSpecialPanel))
{
   panel.Dispose();
}
theSpecialPanel.Dispose();

这篇关于对象需要以特定的顺序排列:这是一个代码的味道?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 22:19