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