结合使用处理异常时的混淆行为

Confusing behaviour when handling exceptions in combination with using

问题

我目前正在实施 UOW 模式,并且遇到异常处理的奇怪行为,这阻碍了我的进步。

我的 UOW 结构如下所示:

public abstract class UnitOfWork : IDisposable {
    public virtual void Save() {
        if (_madeAction) ThrowInvalidCall();
        _madeAction = true;
    }
    public virtual void Cancel() {
        if (_madeAction) ThrowInvalidCall();
        _madeAction = true;
    }
    public virtual void Dispose() {
        if (!_madeAction) {
            Cancel();
            throw new UnitOfWorkAborted("Unit of work was aborted and automatically rolled back!");
        }
    }
    private bool _madeAction = false;
    private void ThrowInvalidCall() => throw new InvalidOperationException($"{nameof(Save)} or {nameof(Cancel)} can only be called once in a unit of work!");
}

[Serializable]
public class UnitOfWorkAborted : Exception {
    public UnitOfWorkAborted() { }
    public UnitOfWorkAborted(string message) : base(message) { }
    public UnitOfWorkAborted(string message, Exception inner) : base(message, inner) { }
}

public interface IUnitOfWorkFactory {
    UnitOfWork CreateNew();
}

我希望按如下方式使用此 UOW:

try {
    using (var uow = uowFactory.CreateNew()) {
        // Do some operation
        throw new InvalidCastException(); // Oh, something went wrong.
        uow.Save();
    }
} catch (UnitOfWorkAborted ex) {
    // Handle exception
}

问题显然是,我的 try/catch 子句永远不会处理异常,因为它只处理 UnitOfWorkAborted,它只在 InvalidCastException.

我的问题是,有什么方法可以让我按照预期的方式使用我的 UOW? (我想复制这种行为 -> TransactionScope

我希望让创建和管理 UOW 的代码尽可能简单。

如果可能的话,我什至希望将实际异常作为 UnitOfWorkAborted.

的内部异常

Observations/Attempts

1。我可以捕获所有异常并将其转换为 UnitOfWorkAborted.
而不是捕获 UnitOfWorkAborted
try {
    using (var uow = uowFactory.CreateNew()) {
        throw new InvalidCastException();
        uow.Save();
    }
} catch (Exception ex) {
    UnitOfWorkAborted uowEx = ex as UnitOfWorkAborted;
    if (uowEx is null) throw ex;

    // Handle exception
}
2。为 Exception.
添加一个 catch 子句
try {
    using (var uow = uowFactory.CreateNew()) {
        throw new InvalidCastException();
        uow.Save();
    }
} catch (UnitOfWorkAborted ex) {
    // Handle exception
} catch (Exception ex) {
    throw ex;
}

我通过实验发现了这个,它工作得很好。是否有可能得到关于为什么这样做的细节的侧面解释,我非常想知道。无论哪种方式,语法都具有令人难以置信的误导性,甚至比第一次尝试更糟糕,当然这不是选择,只是看看它。

这两次尝试真的是我解决这个问题的唯一选择吗?

我最终使用了 Jeremy Lakeman 在评论中建议的回调方法,最终运行良好,并捕获了内部异常。