我在Windows Forms桌面应用程序上工作,该应用程序由表示对象的模型组成,从Web服务,业务层和UI层获取数据。
我刚刚完成了应用程序,现在我尝试对其进行单元测试并通过尝试捕获所有异常,并在业务层中捕获错误:
public List<QlmResult> ReleaseBulkKeys(List<string> externalUserIdReleaseList, string activationKey)
{
try
{
List<QlmResult> qlmResultList = new List<QlmResult>();
string response = string.Empty;
foreach (string externalId in externalUserIdReleaseList)
{
licenseAuthntication.ReleaseLicense(licenseAuthntication.DefaultWebServiceUrl, activationKey, externalId, out response);
qlmResultList.Add(new QlmResult { ComputerKey = externalId, Result = response });
}
return qlmResultList;
}
catch (Exception ex)
{
string errorMsg = LoggingManager.CreateExceptionString(ex);
LoggingManager.SaveExceptionToLogFile(errorMsg);
throw; // To send Exception to UI Layer;
}
}
现在我在Business层中捕获异常并将其记录到log.txt文件中,但我还想在UI中向用户显示例外消息,如
MessageBox.Show(ex.ToString());
所以我用了扔;在BL catch {}块中,我将另一个try {} catch {}添加到UI方法中,如下所示:
private void btnBulkRelease_Click(object sender, EventArgs e)
{
try
{
if (currentProduct != null && currentCustomer != null)
{
QlmLicenseManager qlm = new QlmLicenseManager(currentProduct, currentCustomer, configKeys);
List<QlmResult> bulkResult = qlm.ReleaseBulkKeys(externalIdsLstRelease, txtReleaseActivationKey.Text);
foreach (var result in bulkResult)
{
MessageBox.Show(result.Result);
}
}
else
{
MessageBox.Show("You Should Select Customer and Product from Settings.");
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
我的问题:在UI中显示异常并将其记录在BL中是最佳做法,但是我在BL中使用了两个try {} catch块,而在UI中使用了其他块?
我也应该在UI中使用try {} catch {},或者建议仅在商业逻辑方法中使用它?
我想到另外两个解决方案
1-创建一个事件,当BL中存在异常时将触发UI。
2-创建一个包含两个属性的类bool exceptionDetector和string savedException,我将保存BLException并保存在saveException变量中,并将它发送到UI,以便在exceptionDetector从false更改为true时显示它。
这是一个很好的解决方案吗?
答案 0 :(得分:1)
通常我喜欢在单个函数上捕获我的应用程序的所有异常。 这样,您就可以保护所有代码,包括异步调用......
Application.ThreadException += new ThreadExceptionEventHandler(MyCommonExceptionHandlingMethod)
private static void MyCommonExceptionHandlingMethod(object sender, ThreadExceptionEventArgs t)
{
//Exception handling...
}
注意:在Application.ThreadException
Application.Run()
答案 1 :(得分:1)
如果要将其扔到UI层,那么至少要使用自定义Exception。
现在你正在吞下一般例外 这不被认为是一种好的做法
抛出异常的另一个问题是你没有返回有效的行,这可能会有所帮助。
另一种选择是将bool成功或状态枚举作为争论返回 out
我喜欢为无效输入
等消息返回状态枚举答案 2 :(得分:1)
处理和传播异常非常昂贵,我个人认为使用异常来告知用户违反业务规则的行为并不是最佳做法。
在我看来,异常应仅保留应用程序遇到的意外问题,并应详细记录(堆栈跟踪等)到事件日志和/或文件。实际异常例外中提供的信息对最终用户来说通常是无用的,因此它们可能会被屏蔽(即“发生意外错误,请向系统管理员报告”)。
为了在业务层和客户端层之间提供有关业务规则违规和异常事件的信息,我们在每个业务层方法中使用错误类(错误代码和消息)的实例作为ref参数。此实现允许我们轻松地向客户端层中的最终用户提供特定于语言的错误消息,而无需使用有关客户端当前操作的文化的信息来打扰业务层。