处理循环中的所有成员

Disposing of all members in a loop

我有一个非常大的项目,有多个页面,每个页面有很多 IDisposable 个成员。

我正在尝试找出一种方法来处理循环中的所有 IDisposable 成员,这样我就不必在每个 class 上键入 x1.Dispose(); x2.Dispose; ... xn.Dispose

有办法吗?

谢谢。

当然,只要确保您创建了一个列表来保存它们,并使用 try finally 块来保护自己不泄露它们。

// List for holding your disposable types
var connectionList = new List<IDisposable>();    

try
{ 
    // Instantiate your page states, this may be need to be done at a high level

    // These additions are over simplified, as there will be nested calls
    // building this list, in other words these will more than likely take place in methods
    connectionList.Add(x1);
    connectionList.Add(x2);
    connectionList.Add(x3);
}
finally
{
    foreach(IDisposable disposable in connectionList)
    {
        try
        {
            disposable.Dispose();
        }
        catch(Exception Ex)
        {
            // Log any error? This must be caught in order to prevent
            // leaking the disposable resources in the rest of the list
        }
    }
}

但是,这种方法并不总是理想的。嵌套调用的性质将变得复杂,并且要求调用在您的程序体系结构中如此之高,以至于您可能只想考虑在本地处理这些资源。

而且,这种方式在这些Disposable资源比较密集,需要立即释放的场景下是非常失败的。虽然您可以这样做,即跟踪您的 Disposable 元素,然后一次完成所有操作,但最好尝试将对象生命周期设置为 short ,这样的托管资源。

无论你做什么,都要确保不要泄露 Disposable 资源。如果这些是连接线程,并且它们在一段时间内处于非活动状态,那么简单地查看它们的状态然后在不同的地方重新使用它们而不是让它们闲逛也是明智的。

创建将处理所有一次性对象的方法:

public void DisposeAll()
{
    x1.Dispose();
    x2.Dispose();
    x3.Dispose();
    . . .
}

并在需要的地方调用它。

使用反射(未测试):

    public static void DisposeAllMembersWithReflection(object target)
    {
        if (target == null) return;
        // get all fields,  you can change it to GetProperties() or GetMembers()
        var fields = target.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
        // get all fields that implement IDisposable
        var disposables = fields.Where(x => x.FieldType.GetInterfaces().Contains(typeof(IDisposable)));

        foreach (var disposableField in disposables)
        {
            var value = (IDisposable)disposableField.GetValue(target);
            if (value != null)
                value.Dispose();
        }
    }