How to set the InnerException of custom Exception class from its constructor
Solution 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
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
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
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
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.
Admin
Updated on November 06, 2020Comments
-
Admin over 3 years
How can I set the
InnerException
property of anException
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 theException
type is created, so I cannot call it using the base class constructorMyException() :base(...)
etc. -
Rich over 14 yearsThis doesn't help you in the exception's ctor, though.
-
Marc Gravell over 14 yearsI can't think of a sensible example where reflection is the right way to do this...
-
Admin over 14 yearsIt makes sense for dynamic scenarios involving activations of exceptions where the inner exception cannot be known in advance, therefore cannot be passed to the constructor.
-
Marc Gravell over 14 yearsNo, it doesn't. It really doesn't; it breaks encapsulation. Use a static method in the ` : base(SomeMethod(...), ...)` chain.
-
Raquel over 14 years@_NT: For the inner exception to make sense it should occur before the current exception. Typically you want to bubble exceptions up... not down.
-
Raquel over 14 yearsBTW... changing private and internal values with reflection may cause breaking changes in the future. If you do this it's at your own risk.
-
John Saunders over 14 yearsWhy would you doubt this? What basis do you have for making this assessment? If I were Microsoft, I'd change the implementation just to spite fools who depend on internal implementation details of other people's classes.
-
John Saunders over 14 yearsWhat's wrong with Exception innerEx = new Exception("inner"); Exception ex = new Exception("test", innerEx); ?
-
pauloya over 14 yearsHe is trying to modify the object ex which was not created in the context, I create it just for the purpose of demoing. Actually in his case he is trying to modify the this instance.
-
NT_ over 14 yearsBased on the amount of such details that have changed over the past framework updates?
-
Brian over 14 years+1: This answered my own rather silly question of how to force an exception's inner exception to be itself, thus causing fun things like having the ToString() method trigger a stack overflow.
-
rollsch over 7 yearsWhilst this doesn't answer his question directly, it answers what most people who searched for this were looking for.
-
Mike Rosoft over 6 years@Brian: And this is precisely the reason why .NET Framework does not expose setting the inner exception. If an exception can be linked to an existing exception, and this association can never change, then the exception chain is guaranteed to be finite. If you could change the inner exception, you can no longer make this guarantee - you can recursively loop the exception chain to itself.
-
Mike Rosoft about 4 yearsThe real reason isn't that the internal implementation of the
Exception
class could change. (There's no guarantee it won't, but there's no reason to believe it will.) Rather, it's that by accessing and modifying the private fields, you are violating the class invariants: by only allowing an exception to chain to an existing exception and never allowing this association to change, it is guaranteed that the exception chain will always be finite and will never recursively loop to itself. -
Varun Sharma over 2 years@rollsch is right.