为集合中的多个对象创建使用块

Create using blocks for multiple objects in collection

给定以下代码:

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

我想修改此代码,以便 DoAction 在所有使用块(不仅仅是一个)内完成。如果集合包含两个项目,我希望它以这种方式运行:

using(payment.GetModifyLock())
using(paymentItem1.GetModifyLock())
using(paymentItem2.GetModifyLock())
{
    DoAction();
}

这可能吗?

我想我已经使用这段代码解决了这个问题:

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

如果您想创建一个可重复使用的版本,您可以将功能包装到一个 IDisposable 助手中 class。这很天真,不推荐用于生产代码,但它是一个简单、可重用的抽象。

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

您可以使用以下方法对其进行测试:

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

输出:

Parent locker created
Child locker created
Child locker created
action
Child locker disposed
Child locker disposed
Parent locker disposed