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

C#.NetExceptionLoggingReflection

C# Problem Overview


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.

C# Solutions


Solution 1 - C#

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 2 - C#

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 3 - C#

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 4 - C#

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 - C#

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 - C#

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 - C#

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

Solution 8 - C#

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 - C#

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 - C#

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Question_NTView Question on Stackoverflow
Solution 1 - C#Marc GravellView Answer on Stackoverflow
Solution 2 - C#Paolo TedescoView Answer on Stackoverflow
Solution 3 - C#Meta-KnightView Answer on Stackoverflow
Solution 4 - C#doveView Answer on Stackoverflow
Solution 5 - C#pauloyaView Answer on Stackoverflow
Solution 6 - C#JoeyView Answer on Stackoverflow
Solution 7 - C#NT_View Answer on Stackoverflow
Solution 8 - C#user2278642View Answer on Stackoverflow
Solution 9 - C#shA.tView Answer on Stackoverflow
Solution 10 - C#Mike McWilliamsView Answer on Stackoverflow