如何设置.NET异常对象的InnerException

时间:2009-09-23 15:35:58

标签: c# .net exception logging reflection

当我在该对象的构造函数中时,如何设置InnerException对象的Exception属性?这归结为查找和设置没有setter的属性的支持字段。

顺便说一句:我已经看过这个evain.net - Getting the field backing a property using Reflection但是如果可能的话,还要寻找非基于IL的解决方案。

Exception的构造函数是创建Exception类型的位置,因此我无法使用基类构造函数MyException() :base(...)等来调用它。

9 个答案:

答案 0 :(得分:76)

通过调用base ctor来设置内部异常:

public MyException(string message, Exception innerException)
       : base(message, innerException) {...}

如果需要运行一些代码来获取异常,请使用静态方法:

public MyException(SomeData data) : base(GetMessage(data), GetInner(data)) {...}
static Exception GetInner(SomeData data) {...} // <===== your type creation here!
static string GetMessage(SomeData data) {...}

答案 1 :(得分:37)

Exception类有一个重载的构造函数接受内部异常作为参数:

Exception exc = new Exception("message", new Exception("inner message"));

这是你在找什么?

答案 2 :(得分:13)

为什么不能只将内部异常作为参数调用构造函数?如果由于某种原因无法实现,System.Exception中的支持字段为:

private Exception _innerException;

我使用Redgate's Reflector找到了它。使用反射我想你可以设置内部异常。

编辑:在大多数情况下,通过反射访问私有字段并不是一个好主意,但我不太了解NT的情况,以确定它是好主意还是坏主意。< / p>

答案 3 :(得分:8)

Exception exceptionWithMoreInfo = new Exception("extra info", ex);

通常的做法是假设你已经陷入了一个例子,你想在冒泡之前添加更多信息。

答案 4 :(得分:2)

如果我理解你的问题,你想做这样的事情:

Exception ex = new Exception("test");
Exception innerEx = new Exception("inner");
ex.GetType().GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(ex, innerEx);

如果您在继承自Exception的对象的构造函数中,则使用this而不是第一个ex

但这可能不是处理你想要处理的任何事情的最佳方法。

答案 5 :(得分:1)

使用InnerException构造函数时是不是应该设置Exception(string, Exception)?我认为按照设计你不能改变它,但你总是可以在施工时遵从相应的构造函数:

class MyException : Exception {
    public MyException()
        : base("foo", new Exception("bar"))
    {
        ...
    }

    ...
}

我认为您不应该破坏代码中的异常链,因为这通常会导致您再也找不到错误。

答案 6 :(得分:1)

使用Redgate的Reflector查找字段。我怀疑异常实现是否会改变......但这是一种风险!

答案 7 :(得分:0)

我知道我参加派对的时间已经很晚了,但我觉得这很有效。

public class MyException: Exception
{
    public void SetInnerException(Exception exception) 
    {
        typeof(Exception)
            .GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
            .SetValue(this, exception);
    } 
}

诀窍是获取实际的Exception类型的_innerException字段,然后将内部异常值设置为您的类实例(在这种情况下为MyException)。< / p>

这也适用于变量。

Exception mainException = new Exception();
typeof(Exception)
    .GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
    .SetValue(mainException , new Exception("Something bad happened!"));

答案 8 :(得分:0)

在我的情况下,我使用了以下代码:

class Foo 
{
    void Bar(MyException myException = null)
    {
        try
        {
            SomeActions.Invoke();
        }
        catch (Exception ex)
        {
            if (myException != null)
            {
                // Here I regenerate my exception with a new InnerException
                var regenMyException = (MyException)System.Activator.CreateInstance(myException.GetType(), myException.Message, ex);
                throw regenMyException;
            }

            throw new FooBarException("Exception on Foo.Bar()", ex);
        }
    }
}

有人;)。