'How to set the InnerException of custom Exception class from its constructor

How can I set the InnerException property of an Exception object, while I'm in the constructor of that object? This boils down to finding and setting the backing field of a property that has no setter.

BTW: I have seen this evain.net - Getting the field backing a property using Reflection but looking for non IL-based solution, if possible.

The constructor of Exception is the place where the Exception type is created, so I cannot call it using the base class constructor MyException() :base(...) etc.



Solution 1:[1]

Why can't you just call the constructor taking the InnerException as a parameter? If for some reason it's not possible, the backing field in System.Exception is:

private Exception _innerException;

I found it out using Redgate's Reflector. Using reflection I suppose you could set the inner exception.

Edit: In most cases it's not a good idea to access private fields via reflection, but I don't know enough about NT's case to know for sure if it's a good or bad idea.

Solution 2:[2]

You set the inner exception by calling the base ctor:

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

If you need to run some code to get the exception, use a static method:

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

Solution 3:[3]

The Exception class has an overloaded constructor accepting the inner exception as a parameter:

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

Is this what you are looking for?

Solution 4:[4]

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

would be normal practice assuming you've trapped an exception to which you'd like to add more information before bubbling up.

Solution 5:[5]

If I understand your question you want to do something like this:

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

If you are in the constructor of an object that inherits from Exception you would use this instead of the first ex.

But this may not be the best way to handle whatever it is you are trying to handle.

Solution 6:[6]

Isn't InnerException supposed to be set when using the Exception(string, Exception) constructor? I think it's by design that you can't change this otherwise but you can always defer to the appropriate constructor at construction time:

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

    ...
}

I think you shouldn't ever break the exception chain in your code since that usually leads to errors you will never find again.

Solution 7:[7]

Use Redgate's Reflector to find the field. I doubt the Exception implementation will ever change... But it is a risk!

Solution 8:[8]

I know I'm really late to the party, but I find that this works.

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

The trick is to get the actual Exception type's _innerException field, and then set the inner exception value to your class instance (MyException in this case).

This also works for variables.

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

Solution 9:[9]

In my situation I used this code:

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);
        }
    }
}

HTH someone ;).

Solution 10:[10]

Extension methods work well.

namespace MyNamespace
{
    public static class ExceptionExtensions
    {
        public static void SetInnerException(this Exception exception, string innerExceptionMessage)
        {
            typeof(Exception)
                .GetField("_innerException", BindingFlags.NonPublic | BindingFlags.Instance)
                .SetValue(exception, new Exception(innerExceptionMessage));
        }
    }
}

Then in your catch block when you want to add the inner exception:

try
{
    throw new Exception("Main Message");
}
catch (Exception ex)
{
    ex.SetInnerException("Inner Message");
    throw;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Paolo Tedesco
Solution 4 dove
Solution 5 pauloya
Solution 6 Joey
Solution 7 NT_
Solution 8
Solution 9 shA.t
Solution 10 Mike McWilliams