Question

Going along the same ideas found in this question. I need to be able to recreate an exception inside a function that doesnt know ahead of time what kinds of exceptions will be passed in.

My code so far:

//Code where original exception in created
ArgumentException ex = new ArgumentException(SixteenthsFractional, "Not a recognized architectural string");
RecievingCode(ex, ex.GetType());
throw ex;


public static void RecievingCode(Exception passedException, Type passedExceptionType)
{
    var exception = Activator.CreateInstance(passedExceptionType);
    //Can I cast the passedException to this type?
}

How can I recreate the specific exception just like the person did with the Child1 object in the answer in this question?

(This is not a system architecture question. I have my reasons for why I need to do it this way)

Était-ce utile?

La solution

An object has a type, and that object will always have that type regardless of what you cast it to. So even though your parameter is

Exception passedException

It still is an ArgumentException. The method just accepts "any Exception type". You can safely cast an Exception back to the actual type of the object, but to do so you'll need to know what type it was in the first place:

ArgumentException argEx = passedException as ArgumentException;
if (argEx != null)
{
    ...
}

or

if (passedException is ArgumentException)
{
    ArgumentException argEx = (ArgumentException)passedException;        
}

You can't switch on types though, so this will result in a whole bunch of if/else statements if you have a bunch of different functionality for each exception type.

Autres conseils

If you use generic type inference, you can do this:

public static void RecievingCode<TException>(TException passedException) where TException : Exception
{
    // stuff
}

You would call it like this:

RecievingCode(ex);

Although only types derived from Exception can be thrown or caught, the are very few rules about what such types can do or contain, and such rules are not sufficient to guarantee the existence of any general-purpose means via which instances of any and all such types can be recreated. Certainly types can be designed to be "difficult", and while most types would have little reason for doing so, there's no guarantee that the creator of a type wouldn't find some benefit to a design which happens to be incompatible with any straightforward copying approach.

For example, consider the following sketch of an exception derivative:

void SillyException : Exception
{
    SillyException shouldBeThis;
    public SillyException()
    {
      shouldBeThis = this;
    }
    public override String ToString()
    {
      if (shouldBeThis != this) doSometingBad();
      return base.ToString();
    }
}

Code which knows about field shouldBeThis might be able to use Reflection to set it, but there would be no way for code which had no reason to suspect the existence of a variable to properly set it to this. While that particular example is of course highly contrived, there are a variety of similar reasons why copying an exception may be essentially impossible. For example, a class might keep a ThreadStatic variable which holds the exception--if any--thrown by the last attempted operation on the class on that thread, and so that if cleanup fails it can build a composite exception which combines the original exception with cleanup exception(s). If multiple exceptions include references to each other, an attempt to copy the exception which isn't aware of the different exceptions and their relationships could easily result in a broken object graph, which could cause an attempt to examine and report what happened to crash with a stack overflow.

If you know enough about the exceptions that will be thrown to know that such designs are not an issue, then an approach using generics and Reflection might be usable, but the suitability of such designs will depend upon exactly what you know and exactly what you're trying to do.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top