Tomer Something
Tomer Something

Reputation: 780

Disposing of all members in a loop

I have a very large project with multiple pages, where each page has many IDisposable members.

I'm trying to figure out a way to dispose all the IDisposable members in a loop so I won't have to type x1.Dispose(); x2.Dispose; ... xn.Dispose on each class.

Is there a way to do this?

Thank you.

Upvotes: 2

Views: 1510

Answers (3)

Pablo notPicasso
Pablo notPicasso

Reputation: 3161

Using reflection (not tested):

    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();
        }
    }

Upvotes: 2

SᴇM
SᴇM

Reputation: 7213

Create method which will dispose all your disposable objects:

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

and call it wherever you need it.

Upvotes: 0

Travis J
Travis J

Reputation: 82297

Sure, just make sure that you create a list to hold them, and a try finally block to protect yourself from leaking them.

// 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
        }
    }
}

However, this approach is not always ideal. The nature of the nested calls will get complicated and require the call to be so far up in the architecture of your program that you may want to consider just locally handling these resources.

Moreover, this approach critically fails in the scenario where these Disposable resources are intensive and need to be immediately released. While you can do this, i.e. track your Disposable elements and then do it all at once, it is best to try to get the object lifetime as short as possible for managed resources like this.

Whatever you do, ensure not to leak the Disposable resource. If these are connection threads, and they are inactive for some period of time, it may also be wise to simply look at their state and then re-use them in different places instead of letting them hang around.

Upvotes: 3

Related Questions