C#基于事件封装捕获异常从而减少try catch

一般情况下,我们在开发winform程序的时候,按钮点击事件等这些异常的处理都是手动写try/catch实现,就如下面的代码:

private void BtnCalculate_Click(object? sender, EventArgs e)
{
    try
    {
        //业务逻辑
    }
    catch (Exception ex) 
    {
        MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

这样会在程序中到处都会有一堆重复的代码,如何能对这些异常进行统一的管理,这里看到老A提供的一个处理思路很好。

对EventHandler进行封装

根本目的就是让执行事件处理程序的时候在外面人为地套一个Try/Catch,并对捕获的异常进行相应的处理。从这个意义上讲,如果我们能够对EventHandler或者EventHandler<TEventArgs>进行相应的封装,就能实现我们需要的目的。

我们新建一个EventHandlerWrapper的类,代码实现如下:

public class EventHandlerWrapper
{
    public object Target { get; private set; }
    public MethodInfo Method { get; private set; }
    public EventHandler Hander { get; private set; }

    public EventHandlerWrapper(EventHandler eventHandler)
    {
        if (null == eventHandler)
        {
            throw new ArgumentNullException("eventHandler");
        }
        this.Target = eventHandler.Target;
        this.Method = eventHandler.Method;
        this.Hander += Invoke;
    }

    public static implicit operator EventHandler(EventHandlerWrapper eventHandlerWrapper)
    {
        return eventHandlerWrapper.Hander;
    }

    private void Invoke(object sender, EventArgs args)
    {
        if (null != Form.ActiveForm)
        {
            Form.ActiveForm.Cursor = Cursors.WaitCursor;
        }
        try
        {
            this.Method.Invoke(this.Target, new object[] { sender, args });
        }
        catch (TargetInvocationException ex)
        {
            StringBuilder message = new StringBuilder();
            message.AppendLine(string.Format("Message: {0}", ex.InnerException.Message));
            message.AppendLine(string.Format("Exception Type: {0}", ex.InnerException.GetType().AssemblyQualifiedName));
            message.AppendLine(string.Format("Stack Trace: {0}", ex.InnerException.StackTrace));
            EventLog.WriteEntry("Application", message.ToString(), EventLogEntryType.Error, 0);
            MessageBox.Show(ex.InnerException.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        finally
        {
            if (null != Form.ActiveForm)
            {
                Form.ActiveForm.Cursor = Cursors.Default;
            }
        }
    }
}

EventHandlerWrapper通过EventHandler对象创建,并将EventHandler的Target和Method赋值给EventHandlerWrapper的同名属性。此外,EventHandlerWrapper得Invoke方法中,将对Method的调用放在一个Try/Catch中,并对捕获的异常进行简单的处理:记录到EventLog中在通过MessageBox将相关异常信息显示出来。而EventHandlerWrapper的Handler属性就是对该Invoke方法的直接反映。最后定义了一个隐式类型转换将EventHandlerWrapper直接转换成EventHandler。转化后返回的就是反映Invoke方法的Handler属性。

写一个示例程序,界面如下:

C#基于事件封装捕获异常从而减少trycatch

代码如下:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        //一般的事件调用
        //btnCalculate.Click += BtnCalculate_Click;

        //使用委托封装后的事件调用
        btnCalculate.Click += new EventHandlerWrapper(BtnCalculate_Click);
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    }

    private void BtnCalculate_Click(object? sender, EventArgs e)
    {
        double num1 = double.Parse(txtNum1.Text);
        double num2 = double.Parse(txtNum2.Text);
        double result = num1 / num2;
        txtNum3.Text = result.ToString();
    }
}

一般的事件调用,我们需要手动处理try/catch,而使用封装后的EventHandlerWrapper我们并不需要去手动处理了。


本文内容参考https://www.cnblogs.com/artech/archive/2010/03/26/1697298.html