C# 在这种情况下捕获异常的最佳实践是什么

C# 在这种情况下捕获异常的最佳实践是什么,c#,.net,exception,C#,.net,Exception,我在Windows窗体桌面应用程序上工作,该应用程序由表示对象的模型组成,从web服务、业务层和UI层获取数据 我刚刚完成了应用程序,现在我尝试对其进行单元测试,并通过尝试和捕获业务层中的错误来处理所有异常,如下所示: public List<QlmResult> ReleaseBulkKeys(List<string> externalUserIdReleaseList, string activationKey) { try

我在Windows窗体桌面应用程序上工作,该应用程序由表示对象的模型组成,从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;
        }
    }
    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());
        }
    }
所以我用扔;在BL catch{}块中,我将另一个try{}catch{}放入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;
        }
    }
    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());
        }
    }
private void btnBulkRelease\u单击(对象发送方,事件参数e)
{
尝试
{
if(currentProduct!=null&¤tCustomer!=null)
{
QLMICenseManager qlm=新的QLMICenseManager(currentProduct、currentCustomer、configKeys);
List bulkResult=qlm.ReleaseBulkKeys(externalDSLStrease,txtreaseActivationKey.Text);
foreach(bulkResult中的var结果)
{
MessageBox.Show(result.result);
}
}
其他的
{
Show(“您应该从设置中选择客户和产品。”);
}
}
捕获(例外情况除外)
{
Show(例如ToString());
}
}
我的问题:在UI中显示异常并在BL中记录它是最佳实践吗?但我使用两个try{}catch块,一个在BL中,另一个在UI中

我应该在UI中使用try{}catch{},还是建议只在业务逻辑方法中使用它

我考虑另外两种解决方案

1-创建一个事件,当BL中出现异常时将触发UI

2-创建一个包含两个属性bool exceptionDetector和string savedException的类,我将在savedException变量中保存BL异常,并将其发送到UI,以便在exceptionDetector从false更改为true时显示它


这是一个好的解决方案吗?

通常我喜欢在一个函数中捕获应用程序上的所有异常。 这样,您就可以保护所有代码,包括异步调用

Application.ThreadException += new ThreadExceptionEventHandler(MyCommonExceptionHandlingMethod)

private static void MyCommonExceptionHandlingMethod(object sender, ThreadExceptionEventArgs t)
{
    //Exception handling...
}

注意:在
Application.Run()之前添加
Application.ThreadException
,如果要将其抛出UI层,则至少使用自定义异常

现在在网络中,你正在吞咽一个普遍的例外
这被认为是不好的做法

抛出异常的另一个问题是没有返回有效的行,这可能会有所帮助

另一个选项是返回布尔成功或状态枚举作为参数


我喜欢返回一个状态枚举,比如无效输入

< P>处理和传播异常是非常昂贵的,我个人认为最好不要使用异常来通知用户违反业务规则。p> 在我看来,异常应该只保留给应用程序遇到的意外问题,并且应该详细记录(堆栈跟踪等)到事件日志和/或文件中。实际异常中提供的信息通常对最终用户没有用处,因此它们可能会被屏蔽(即“发生意外错误,请向系统管理员报告”)


为了提供有关业务层和客户端层之间的业务规则冲突和异常发生的信息,我们在每个业务层方法中使用错误类(错误代码加消息)的实例作为ref参数。此实现使我们能够轻松地向客户端层内的最终用户提供特定于语言的错误消息,而无需向业务层提供有关客户端当前运行的文化的信息。

解决方案2-最合适,但在UI中创建异常类,存储异常后,终止BL进程,并在BL完成时在UI中测试异常类。这不是好方法。如果您正在编码try..catch每个方法上的异常,则说明您做错了。捕获bll中的示例仅用于包装它们或添加上下文信息。使用异常处理策略来实际处理异常。