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

33,212

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.

Share:
33,212
Admin
Author by

Admin

Updated on November 06, 2020

Comments

  • Admin
    Admin over 3 years

    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.

  • Rich
    Rich over 14 years
    This doesn't help you in the exception's ctor, though.
  • Marc Gravell
    Marc Gravell over 14 years
    I can't think of a sensible example where reflection is the right way to do this...
  • Admin
    Admin over 14 years
    It 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
    Marc Gravell over 14 years
    No, it doesn't. It really doesn't; it breaks encapsulation. Use a static method in the ` : base(SomeMethod(...), ...)` chain.
  • Raquel
    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
    Raquel over 14 years
    BTW... 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
    John Saunders over 14 years
    Why 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
    John Saunders over 14 years
    What's wrong with Exception innerEx = new Exception("inner"); Exception ex = new Exception("test", innerEx); ?
  • pauloya
    pauloya over 14 years
    He 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_
    NT_ over 14 years
    Based on the amount of such details that have changed over the past framework updates?
  • Brian
    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
    rollsch over 7 years
    Whilst this doesn't answer his question directly, it answers what most people who searched for this were looking for.
  • Mike Rosoft
    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
    Mike Rosoft about 4 years
    The 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
    Varun Sharma over 2 years
    @rollsch is right.