Create using blocks for multiple objects in collection

Given the following code:

using (payment.GetModifyLock())
{
    foreach (var paymentItem in paymentItems)
    {
        using (paymentItem.GetModifyLock())
        {
            
        }
    }
    DoAction();
}

I’m looking to modify this code so that DoAction is done inside all the using blocks (not just one). If the collection contains two items, I’d want it to function in this way:
using(payment.GetModifyLock())
using(paymentItem1.GetModifyLock())
using(paymentItem2.GetModifyLock())
{
    DoAction();
}

Is this possible?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

If you wanted to create a more reusable version of what you have, you can wrap the functionality into an IDisposable helper class. This is naïve and not recommended for production code, but it is a simple, reusable abstraction.

public class NestedLocker : IDisposable
{
    private readonly IDisposable _parentLocker;
    private readonly Queue<IDisposable> _childLockers = new Queue<IDisposable>();
    
    public NestedLocker(Func<IDisposable> parentLocker, 
        IEnumerable<Func<IDisposable>> childLockers)
    {
        _parentLocker = parentLocker();
        
        foreach (var childLocker in childLockers)
        {
            _childLockers.Enqueue(childLocker());
        }
    }

    public void Dispose()
    {
        foreach (var childLocker in _childLockers)
        {
            childLocker.Dispose();
        }
        
        _parentLocker.Dispose();
    }
}

You can test it with the following:
void Main()
{
    Func<IDisposable> parentLocker = () => new ParentLocker();
    List<Func<IDisposable>> childLockers = 
        new List<Func<IDisposable>> { () => new ChildLocker(), () => new ChildLocker() };
    using (new NestedLocker(parentLocker, childLockers))
    {
        Console.WriteLine("action");
    }
}

public class ParentLocker : IDisposable
{
    public ParentLocker()
    {
        Console.WriteLine("Parent locker created");
    }
    
    public void Dispose()
    {
        Console.WriteLine("Parent locker disposed");
    }
}

public class ChildLocker : IDisposable
{
    public ChildLocker()
    {
        Console.WriteLine("Child locker created");
    }
    
    public void Dispose()
    {
        Console.WriteLine("Child locker disposed");
    }
}

which outputs:
Parent locker created
Child locker created
Child locker created
action
Child locker disposed
Child locker disposed
Parent locker disposed

Method 2

Think I’ve figured this out using this code:

using (payment.GetModifyLock())
{
    var locks = new List<DistributedLock>();
    try
    {
        foreach (var paymentItem in paymentItems)
        {
            locks.Add(paymentItem.GetModifyLock());
        }

        // Do action
    }
    finally
    {
        foreach (var locker in locks)
        {
            locker.Dispose(); ;
        }
    }
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x