结合使用处理异常时的混淆行为
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
}
- 缺点:
- 我需要将异常转换为 UnitOfWorkAborted 并且这会添加应该可以避免的代码,因为:
- 什么是 try/catch 那么即使不指定要处理的异常?这种做法就是感觉..呃.
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 在评论中建议的回调方法,最终运行良好,并捕获了内部异常。
问题
我目前正在实施 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.
而不是捕获 UnitOfWorkAbortedtry {
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
}
- 缺点:
- 我需要将异常转换为 UnitOfWorkAborted 并且这会添加应该可以避免的代码,因为:
- 什么是 try/catch 那么即使不指定要处理的异常?这种做法就是感觉..呃.
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 在评论中建议的回调方法,最终运行良好,并捕获了内部异常。