C#将异常从类传递到窗体

3

如何在创建类的实例时传递错误信息。

类:

class ThreadSafeLog
{
  public ThreadSafeLog()
  {
    try
    {
      if (!File.Exists(Path_))
      {
        using (File.Create(Path_)) { }
      }
    }
    catch(Exception e)
    {
      MessageBox.Show(e.Message);//error transmit exception to Form
    }
  }
}

表单:

ThreadSafeLog log = new ThreadSafeLog(
  @"R:\project\ThreadSafeLog\ThreadSafeLogTest\ThreadSafeLogTest\bin\");

我不理解这个问题... - mswietlicki
2个回答

2
为什么ThreadSafeLog需要关注使用它的表单在做什么?它怎么知道它被一个表单使用了呢?应该在表单中捕获异常。
class ThreadSafeLog
{
    public ThreadSafeLog()
    {
        if (!File.Exists(Path_))
        {
            using (File.Create(Path_)) { }
        }
    }
}

表单:

try
{
    ThreadSafeLog log = new ThreadSafeLog(
        @"R:\project\ThreadSafeLog\ThreadSafeLogTest\ThreadSafeLogTest\bin\");
}
catch (Exception ex)
{
    MessageBox.Show(e.Message);
}

尽管如Adriano所指出的那样,您可能还想问为什么要直接向用户显示内部错误详情。

0

我不会通知日志记录器本身内部的错误给日志的使用者。通常,日志是一个子系统,它应该被认为是安全的,并且线程安全,否则你的代码将变得 混乱。想象一下:

try
{
    // Do something that may fail
}
catch (SomeException e)
{
    try
    {
        logger.Log(e);
    }
    catch (IOException)
    {
        // Ooops, log doesn't work. What should I do?
        // Should I display a MessageBox?
    }
}

你的代码很快就会变得混乱(想象一下为每个跟踪日志重复执行相同的检查)。

我会做的是在日志函数内忽略(如果可能的话)错误并采取其他措施。如何实现?只需向日志类添加一个事件(以下代码仅供示例,不用于生产!):

class Logger
{
    public event EventHandler<LogErrorEventArgs> Error;

    public void Log(Exception e)
    {
        try
        {
            // Try to write log somewhere...
        }
        catch (IOException internalException)
        {
            EventHandler<LogErrorEventArgs> error = Error;
            if (error != null)
                error(this, new LogErrorEventArgs(e, internalException);
        }
    }
}

这样,记录器内部未处理的错误将不会被注意到(如果适用),或者它们可以被处理(以适当的方式,如果有的话)。例如:

Logger logger = new Logger();
logger.Error += delegate(object sender, LogErrorEventArgs e)
{
    if (SystemInformation.UserInteractive)
        MessageBox.Show(e.ExceptionToLog.Message);
};

你可以附加多个处理程序(例如记录到Windows日志并通知用户会话是否交互)。当你使用日志时,你不会意识到它可能会失败(因此你不必在代码中到处填写try/catch),但如果需要,你仍然可以被通知,并且日志内部的错误将以一致的方式处理。

现在让我们像这样重写我们第一个示例中的代码:

try
{
    // Do something that may fail
}
catch (SomeException e)
{
    logger.Log(e);
}

很直接,对吧?我认为记录器将始终编写异常(某种方式),但更改代码以处理原始的 String 很容易。我省略了 LogErrorEventArgs 的代码,因为它很明显可能是这样的:

class LogErrorEventArgs : EventArgs
{
    public LogErrorEventArgs(
                            Exception exceptionToLog,
                            Exception internalLoggerException)
    {
        ExceptionToLog = exceptionToLog;
        InternalLoggerException = internalLoggerException;
    }

    public Exception ExceptionToLog
    {
        get;
        set;
    }

    public Exception InternalLoggerException
    {
        get;
        set;
    }
}

@mzk 只需将 Logger 替换为 ThreadSafeLog,就完成了。不要忘记将 File.Create() 移到构造函数之外(或传递一个用于 Error 事件的委托作为参数)。通常,以这种方式(使用 不可预测 异常)放置可能失败的代码在类型构造函数中并不是一个好主意;我会使用初始化方法或者在第一次使用时创建文件。不要忘记,不仅文件创建可能失败,文件写入也可能失败(因为并发、权限、磁盘空间等原因...)。 - Adriano Repetti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接