假设我有一个 WinForms 组件。
它可以是基于 System.ComponentModel.Component 的类或System.Windows.Forms.Control类(实际上 Control
继承 Component
)。
我的组件可能使用其他我们应该正确处理的 .NET 类 - Pens、Brushes、ContextMenuStrips 等。我按照 Dispose(bool disposing)
的实现中的预期方式处理它们。根据众所周知的方法IDisposable模式。
我想知道,何时我必须添加一个接受 IConatiner 的特殊构造函数参数,以便表单设计器将注册我的组件的实例,以便在表单关闭期间自动资源处置:
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
...
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
}
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
我分析了Dispose(bool disposing)
的源代码一些WinForms组件的方法试图找到答案,但情况仍然不清楚。
例如,ContextMenuStrip
组件有这样一个构造函数,但是DataGridView
没有 - 尽管两者都有足够的对象在其 Dispose(bool disposing)
中处置实现。
有什么提示或想法吗?
最佳答案
如果您是组件作者,作为最佳实践,我的建议是实现接受 IContainer
的构造函数重载,因为当组件具有此类构造函数时,当开发人员将该组件的实例删除到设计表面上,设计者生成一段关心组件处置的代码。
您的组件在 ToolBox 中可用吗?
对于可通过工具箱访问的组件,如果用户将组件拖放到设计器上,那么他们不应该担心组件的处置。所有标准组件都遵循这种模式,用户从不关心如何处理他们通过设计器创建的控件和组件,因此组件作者有责任关心设计时支持。
您的组件中是否有需要处理的内容?
如果你没有任何东西要处理,那么这个重载并不那么重要,但是如果你有任何东西要处理,那么你应该关心处理。正如前面的要点中提到的,由于用户可能会将您的组件放在设计器上并指望设计器来处理它们,那么您有责任提供该方法,以便设计器生成处理代码。否则,组件将不会被释放,从而导致内存/句柄泄漏。
作为组件用户
作为组件用户,如果您在代码中创建组件(并且不在设计时删除它),那么您有责任在不再需要该组件时处理该组件。您可能会发现这篇文章很有用:Why should I insert a non-UI Windows.Forms component from the designer?
如果您从工具箱中删除一个组件,则无需担心它的处置。所有标准组件都会生成一个代码,以便在处理表单时处理该组件。
设计器生成的代码如何处理组件的处置?
对于具有接受 IContainer
构造函数的组件,当您将它们放到设计界面上时,设计器会生成一段代码来创建 components
集合并添加组件到该集合,然后在表单处置时处置该集合(包括其所有组件)。
查看以下设计者生成的代码:
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
InitializeComponent()
{
this.components = new System.ComponentModel.Container();
...
...
this.myComponent = new MyComponent(this.components);
...
...
}
和Dispose method of Container类:
protected virtual void Dispose(bool disposing) {
if (disposing) {
lock (syncObj) {
while (siteCount > 0) {
ISite site = sites[--siteCount];
site.Component.Site = null;
site.Component.Dispose();
}
sites = null;
components = null;
}
}
}
您会看到,当您的表单被处置时,它将处置在容器中找到的所有组件。
关于c# - 我们什么时候应该为组件实现带有 IContainer 参数的构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66153587/