问题描述
上下文
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()$每个视图的c $ c>方法。
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();
这篇关于对象需要以特定的顺序排列:这是一个代码的味道?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!