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?
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