使用从System.ComponentModel.Component派生的类实现Dispose()

时间:2008-10-30 15:08:19

标签: c#

我创建了一个派生自Component的类:

public class MyComponent: System.ComponentModel.Component
{


}

我看到Visual Studio为我编写了这段代码:

protected override void Dispose(bool disposing)
{
    try
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
    }
    catch
    {
        throw;
    }
    finally
    {
        base.Dispose(disposing);
    }
}

MyComponent的成员是DataSet,可能还有一些其他成员实施IDisposable。如果有的话,我需要使用Dispose()方法进行修改以确保正确清理事物?谢谢你的帮助。

4 个答案:

答案 0 :(得分:1)

变化:

if (disposing && (components != null))
{
     components.Dispose();
}

是:

if (disposing && (components != null))
{
    _dataset.Dispose();
    components.Dispose();
}

答案 1 :(得分:0)

检查任何一次性成员对象,如果它们不为空,则将其丢弃。

答案 2 :(得分:0)

我想出了这堂课:

public class DisposableComponentWrapper : IComponent
{
    private IDisposable disposable;

    public DisposableComponentWrapper(IDisposable disposable)
    {
        this.disposable = disposable;
    }

    public DisposableComponentWrapper(IDisposable disposable, ISite site)
        : this(disposable)
    {
        Site = site;
    }

    public void Dispose()
    {
        if (disposable != null)
        {
            disposable.Dispose();
        }
        if (Disposed != null)
        {
            Disposed(this, EventArgs.Empty);
        }
    }

    public ISite Site { get; set; }

    public event EventHandler Disposed;
}

和IContainer的扩展方法:

public static void Add(this IContainer container, IDisposable disposableComponent)
{
    var component = (disposableComponent as IComponent);
    if(component == null)
    {
        component = new DisposableComponentWrapper(disposableComponent);
    }
    container.Add(component);
}

这可能有助于那些愿意将可支配资源用于其表格的人。

注意:我不确定IComponent.Disposed的行为,MSDN没有说明如何在实现这个接口时调用它,文档听起来像是在讨论客户端代码注册到该事件比应该由该接口的实现触发的时间更多。

答案 3 :(得分:0)

将一次性用品包装成组件,并将其添加到components集合中。生成的处理模式实现将正确处理它们。

public partial class MyComponent : System.ComponentModel.Component
{
    private readonly System.Data.DataSet _dataSet;

    public MyComponent(System.Data.DataSet dataSet)
    {
        _dataSet = dataSet ?? throw new System.ArgumentNullException(nameof(dataSet));
        components.Add(new DisposableWrapperComponent(dataSet));
    }
}

DisposableWrapperComponent的定义如下:

using System;
using System.ComponentModel;

public class DisposableWrapperComponent : Component
{
    private bool disposed;

    public IDisposable Disposable { get; }

    public DisposableWrapperComponent(IDisposable disposable)
    {
        Disposable = disposable ?? throw new ArgumentNullException(nameof(disposable));
    }

    protected override void Dispose(bool disposing)
    {
        if (disposed) return;

        if (disposing)
        {
            Disposable.Dispose();
        }

        base.Dispose(disposing);

        disposed = true;
    }
}

受到@smoothdeveloper答案的启发。

如果您需要能够重置数据集,则将生存期管理封装在属性中非常有效。

using System;
using System.ComponentModel;
using System.Data;

public partial class MyComponent : Component
{
    private const string DataSetComponentName = "dataSet";

    public DataSet DataSet
    {
        get => (DataSet)((DisposableWrapperComponent)components.Components[DataSetComponentName])
                ?.Disposable;
        set
        {
            var lastWrapper = (DisposableWrapperComponent)components.Components[DataSetComponentName];
            if (lastWrapper != null)
            {
                components.Remove(lastWrapper);
                lastWrapper.Dispose();
            }

            if (value != null)
            {
                components.Add(new DisposableWrapperComponent(value), DataSetComponentName);
            }
        }
    }

    public MyComponent(DataSet dataSet)
    {
        DataSet = dataSet ?? throw new ArgumentNullException(nameof(dataSet));
    }
}

我在实现Windows服务时使用了此方法,该服务在OnStart中创建了一个可抛弃的对象,并在OnStop中对其进行了处理。