使用Expression lambda进行异常处理

时间:2014-06-14 12:54:40

标签: c# .net exception-handling lambda mvp

我的DAL不处理异常,它将传播到将处理异常的演示者类中的调用方法。

我正在使用一个名为ExecutAction(Action action)的处理程序,所以我在一个地方捕获异常,而不是在每个方法中重复。

目前,我没有记录错误。只需提醒用户注意某个操作,并尽可能让系统保持活动状态。

向用户显示消息时,Presenters将使用名为MessagingService的静态类。 (ShowErrorMessage())。这样我就可以在一个地方定制所有按摩盒。

        private void Search()
        {
            ExecutAction(() =>
            {
                var info = _DataService.GetByACNo(_model.AccountNumber);

                    if (info != null)
                    {
                        _Model = info ;
                        this.SetViewPropertiesFromModel(_Model, _View);
                    }
                    else
                    {
                        MessageBox.Show ("Bank account not found");
                    }
                });
            }


            private void ExecutAction(Action action)
            {
                try
                {
                    action();
                }

                catch (NullReferenceException e) { MessagingService.ShowErrorMessage(e.Message); }
                catch (System.Data.SqlTypes.SqlTypeException e) { MessagingService.ShowErrorMessage(e.Message); }
                catch (System.Data.SqlClient.SqlException e) { MessagingService.ShowErrorMessage(e.Message); }
            }
        }

我应该为此包含一般异常处理程序,以便能够处理任何不可预见的异常吗?

你还能告诉我一个更好的方法来处理显示消息而不是使用静态吗?

在每个方法调用(ExecutAction(() =>)中使用lambda语句会降低代码的可读性吗?

当显示用户消息时如何首先显示“检查服务器连接”等自定义消息,然后如果用户想要更多信息(如StackTrace /技术细节),他/她可以按下{{1}之类的按钮在MessageBox对话框中?

2 个答案:

答案 0 :(得分:2)

我认为你的方法对你的工作来说已经足够了。以ExecuteAction包装逻辑对我来说是一种可接受的方式。作为另一种选择,我可能会在实践中使用AOP进行集中式异常处理。

此外,我可能会使用从依赖注入容器中解析的MessagingService而不是静态容器。

关于如何显示错误,这完全取决于您的业务目的。例如,您可以简单地记录错误并告诉用户“出错了”,或者向他们展示完整的堆栈跟踪,包括环境信息,这样他们就可以简单地复制&粘贴在电子邮件中。

答案 1 :(得分:2)

我同意jeffrey关于尝试将IoC用于您的留言服务。您可以定义一个抽象基本presenter类,它依赖于您的消息服务的接口。基类将负责处理委托执行+异常日志记录。

public interface IMessageService
{
    void ShowErrorMessage(Exception e);
}

public abstract class PresenterBase
{
    private readonly IMessageService _messageService;

    public PresenterBase(IMessageService messageService)
    {
        this._messageService = messageService;
    }

    protected void ExecuteAction(Action action)
    {
        try
        {
            action();
        }

        catch (Exception e) { this._messageService.ShowErrorMessage(e); }
    }
}

public class SearchPresenter: PresenterBase
{
    public SearchPresenter(IMessageService messageService)
        : base(messageService)
    {
    }

    public void Search()
    {
        this.ExecuteAction(() =>
        {
            //perform search action
        });
    }
}

关于捕获所有记录的问题。除非你为特定类型的异常做一些特殊的事情,否则我建议你处理所有相同的事情。我提供的示例将异常传递给消息服务,以便您的消息服务可以处理格式细节。

如果您尚未合并任何类型的IoC容器,则始终可以先使用接口注入,然后从子类构造函数中显式传递实例。

public class SearchPresenter: PresenterBase
{
    public SearchPresenter()
        : base(new SomeMessageService())
    {
    }

    ...
}

这至少可以消除静态依赖关系,如果你引入了一个IoC容器,那么以后就不用太多了。