【问题标题】:How to get both exceptions if a child object and a parent object have an exception thrown如果子对象和父对象都抛出异常,如何同时获取异常
【发布时间】:2016-09-29 22:44:26
【问题描述】:

在 C# 中,如果子对象有 try catch 代码块,而父对象也有 try catch 代码块,如果子对象抛出异常,如何获取这两个异常的详细信息?

这里是异常类:

public class CompileObjectException : InvalidOperationException
{
    private ICustomObject _ownerCustomObject { get; set; }
    public ICustomObject OwnerCustomObject
    {
        get
        {
            return _ownerCustomObject;
        }
        set
        {
            _ownerCustomObject = value;
        }
    }
    public CompileObjectException()
    {

    }
    public CompileObjectException(ICustomObject ownerCustomObject, string message)
        : base(message)
    {
        _ownerCustomObject = ownerCustomObject;
    }
}

CompileObjectException在两个对象中都被抛出时,OwnerCustomObject被设置为抛出异常的对象。

在上面的代码中,我想为父对象和子对象获取OwnerCustomObject

【问题讨论】:

    标签: c# exception


    【解决方案1】:

    通常情况下,父对象会在 InnerException 中与子异常一起抛出异常。 InnerExceptions 可以有 InnerExceptions,因此您可以一直深入到根本原因。

    编辑:

    图案看起来像:

    void SomeMethod()
    {
       try
       {
       }
       catch (Exception e)
       {
          throw new MyException(message, e);
       }
    }
    
    class MyException : Exception
    {
       public MyException(string message, Exception inner)
       : base(message, inner)
       {
       }
    }
    

    显然还有其他详细信息,但这就是您将两者都返回的方式。

    【讨论】:

    • 查看 InnerException 时,值为 null。我必须将其编码到我的 CompileObjectException 类中吗?
    • 请注意,在某些情况下,调用者不会明确传播异常信息,而您会得到 null 内部异常 - 即服务器端代码通常具有顶级异常处理程序,这些处理程序将掩盖所有可能泄漏配置的错误像SqlException这样的信息。
    【解决方案2】:

    为了争论,我假设您的 ICustomObject 有一个属性,以及一个实现它的具体类,如下所示:

    public class CustomObject : ICustomObject
    {
        public string Scope { get; set; }
    }
    
    public interface ICustomObject
    {
        string Scope { get; set; }
    }
    

    默认情况下,Exception 类上的 ToString() 方法会递归循环所有 InnerException,以便显示用户可用的所有内容。

    如果您想获取该自定义对象的值,您必须做一些稍微不同的事情。

    首先,修改您的自定义异常类以接受InnerException 并将其传递给base

    public CompileObjectException(ICustomObject ownerCustomObject, string message, Exception innerException = null)
        : base(message, innerException)
    {
        _ownerCustomObject = ownerCustomObject;
    }
    

    然后重写ToString() 方法以循环遍历每个InnerException,并创建一个包含CustomObject 类值的自定义消息:

    public override string ToString()
    {
        return GetInnerException(this);
    }
    
    private string GetInnerException(CompileObjectException e)
    {
        if (e == null)
            return "";
    
        return string.Format("{0} ({1}) \n{2}", e.Message, e.OwnerCustomObject.Scope, GetInnerException((CompileObjectException)e.InnerException));
    }
    

    现在,当您调用多个嵌套方法时,它们每个都抛出一个异常,您可以保存所有这些异常并将它们显示给用户。

    public static void Main()
    {
        try
        {
            ParentMethod();
        }
        catch (Exception e)
        {
            Console.WriteLine(e);  // implicitly calls e.ToString()
        }
    
    }
    
    public static void ParentMethod()
    {
        try
        {
            ChildMethod();
        }
        catch (Exception e)
        {
            throw new CompileObjectException(new CustomObject {Scope = "P"}, "Parent Message", e);
        }
    }
    
    public static void ChildMethod()
    {
        try
        {
            YetAnotherChild();
        }
        catch (Exception e)
        {
            throw new CompileObjectException(new CustomObject {Scope = "C"}, "Child Message", e);
        }
    }
    
    public static void YetAnotherChild()
    {
        throw new CompileObjectException(new CustomObject {Scope = "C2"}, "Another Child Message");
    }
    

    您可能希望针对您的特定情况自定义它,但上面会显示与此类似的链...

    Parent Message (P) 
    Child Message (C) 
    Another Child Message (C2)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多