Preserving exceptions from dynamically invoked methods - c#

Related
Related
I want to dynamically invoke a MethodInfo object and have any exceptions that get thrown from inside of it pass outward as if it were called normally.
I have two options it seems. They're outlined below.
Option 1 maintains the type of the exception thrown by MyStaticFunction, but the StackTrace is ruined because of the throw.
Option 2 maintains the StackTrace of the exception, but the type of the exception is always TargetInvocationException. I can pull out the InnerException and its type, but that means that I can't write this for example:
try { DoDynamicCall(); }
catch (MySpecialException e) { /* special handling */ }
Option 1:
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
try
{
method.Invoke(null, new object[] { 5 });
}
catch (TargetInvocationException e)
{
throw e.InnerException;
}
}
Option 2:
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
method.Invoke(null, new object[] { 5 });
}
What I really want is for callers to DoDynamicCall to receive exceptions as if they had called this:
void DoDynamicCall()
{
MyClass.MyStaticFunction(5);
}
Is there a way to get the benefits of both Option 1 and Option 2?
Edit:
The option I wish I had (invented special new C# keyword rethrow on the spot):
void DoDynamicCall()
{
MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
try
{
method.Invoke(null, new object[] { 5 });
}
catch (TargetInvocationException e)
{
//Magic "rethrow" keyword passes this exception
//onward unchanged, rather than "throw" which
//modifies the StackTrace, among other things
rethrow e.InnerException;
}
}
This would also eliminate the need for this weirdo, because you could use rethrow e; instead:
try { ... }
catch (Exception e)
{
if (...)
throw;
}
In general, it would be a way to decouple throw; from the requirement "I have to be directly in a catch block."

Here's the solution I came up with. It gets the job done. I'm still interested in other answers as there might be something easier or cleaner.
When you want the functionality of throw; but the exception you want to pass on is not the exception of the current catch block, use throw Functional.Rethrow(e);
Replace try...catch... with Functional.TryCatch
Replace try...catch...finally... with Functional.TryCatchFinally
Here's the code:
//Need a dummy type that is throwable and can hold an Exception
public sealed class RethrowException : Exception
{
public RethrowException(Exception inner) : base(null, inner) { }
}
public static Functional
{
public static Exception Rethrow(Exception e)
{
return new RethrowException(e);
}
public static void TryCatch(Action _try, Action<Exception> _catch)
{
try { _try(); }
catch (RethrowException e) { _catch(e.InnerException); }
catch (Exception e) { _catch(e); }
}
public static T TryCatch<T>(Func<T> _try, Func<Exception, T> _catch)
{
try { return _try(); }
catch (RethrowException e) { return _catch(e.InnerException); }
catch (Exception e) { return _catch(e); }
}
public static void TryCatchFinally(
Action _try, Action<Exception> _catch, Action _finally)
{
try { _try(); }
catch (RethrowException e) { _catch(e.InnerException); }
catch (Exception e) { _catch(e); }
finally { _finally(); }
}
public static T TryCatchFinally<T>(
Func<T> _try, Func<Exception, T> _catch, Action _finally)
{
try { return _try(); }
catch (RethrowException e) { return _catch(e.InnerException); }
catch (Exception e) { return _catch(e); }
finally { _finally(); }
}
}
Update
In .NET 4.5 there is the new System.Runtime.ExceptionServices.ExceptionDispatchInfo class. This can be used to capture an exception:
var capturedException = ExceptionDispatchInfo.Capture(e);
And then later this is used to resume throwing the exception:
capturedException.Throw();

No, I don't believe there is a way to have the benefits of both. However, throwing e.InnerException will still allow you to get the original stacktrace, because you can simply use e.InnerException.StackTrace to get the original stack trace. So, in short, you should use option 1.

The best option is Option 3: don't use reflection at all, but instead use Expression<T>.Compile().
Instead of doing this:
static void CallMethodWithReflection(MethodInfo method)
{
try
{
method.Invoke(null, new object[0]);
}
catch (TargetInvocationException exp)
{
throw exp.InnerException;
}
}
Try to aim for this:
private static void CallMethodWithExpressionCompile(MethodInfo method)
{
Expression.Lambda<Action>(Expression.Call(method)).Compile()();
}
The caveat is that you need to know the method signature, although you can write code that dynamically builds the expression to fit one of several signatures.
You may not always be able to use this technique, but when you do it is the best option. For all intents and purposes it is like calling any other delegate. It is also faster than reflection if you make multiple calls (in this case compile only once and keep a handle on the compiled delegate).

I had a similar issue and came up with this:
/// <summary>
/// Attempts to throw the inner exception of the TargetInvocationException
/// </summary>
/// <param name="ex"></param>
[DebuggerHidden]
private static void ThrowInnerException(TargetInvocationException ex)
{
if (ex.InnerException == null) { throw new NullReferenceException("TargetInvocationException did not contain an InnerException", ex); }
Exception exception = null;
try
{
//Assume typed Exception has "new (String message, Exception innerException)" signature
exception = (Exception) Activator.CreateInstance(ex.InnerException.GetType(), ex.InnerException.Message, ex.InnerException);
}
catch
{
//Constructor doesn't have the right constructor, eat the error and throw the inner exception below
}
if (exception == null ||
exception.InnerException == null ||
ex.InnerException.Message != exception.Message)
{
// Wasn't able to correctly create the new Exception. Fall back to just throwing the inner exception
throw ex.InnerException;
}
throw exception;
}
An Example of it's use is below:
try
{
return typeof(MyType).GetMethod(methodName, BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(new[] { myType) })
.Invoke(null, parameters);
}
catch (TargetInvocationException ex)
{
ThrowInnerException(ex);
throw new Exception("Throw InnerException didn't throw exception");
}

Related

Exit the function/method if an exception occurs

I'm trying to find a code to exit the whole method if an exception occurs in a sub method. I tried adding return in catch section of Subfunction() but the process will continue to Thirdfunction()
public static void Mainfunction()
{
try
{
//some code
//some code
Subfunction();
ThirdFunction();
}
catch(Exception ex)
{
//write to log
}
}
public static void Subfunction()
{
try
{
//some code
//some code
}
catch (Exception ex)
{
//write to log
}
}
So basically if an error occured in the Subfuntion() I want to stop the process from the Mainfunction() without continuing to the ThirdFunction(). Any help will be highly appreciated. Thanks
if an error occured in the Subfuntion() I want to stop the process
from the Mainfunction()
The simplest way to remove try/catch in your method Subfunction
If you want to keep the try/catch in this method, (for logging or something), rethrown exception
public static void Main()
{
try
{
Subfunction();
Thirdfunction();
}
catch(Exception ex)
{
}
}
public static void Subfunction()
{
try
{
throw new AccessViolationException();
}
catch (Exception ex)
{
throw;
}
}
There are basically two sets of possible solutions: With use of Exceptions and without.
With the use of exceptions, I'd recommend to just let it bubble up , as I've already said in comments.
Then you can rethrow:
try {
// exception here
}
catch(Exception ex)
{
throw;
// Attention: this is _different_ from "throw ex" !!
}
Pay attention here:
You can also use the throw e syntax in a catch block to instantiate a new exception that you pass on to the caller. In this case, the stack trace of the original exception, which is available from the StackTrace property, is not preserved.
See throw (C# Reference) (emphasis by me)
Coming over from Java myself, this is something people like myself will trip over during transitioning from Java to .Net. So if you got "java guys" new on the team: don't be harsh on them, just point them to the docs.
You can wrap:
try {
// exception here
}
catch(Exception inner)
{
throw new MyCustomException( "Some custom message", inner);
}
BTW: It is generally not a good idea to catch Exception. Most of the time you'd want to catch specific exceptions that you can actually handle.
The other class of solutions is without bubbling up exceptions:
Return value:
public static bool Subfunction()
{
bool success = true;
try
{
//some code
//some code
}
catch (Exception ex)
{
// TODO write error log!
success = false;
}
return success;
}
Or with return or error codes:
// DO NOT USE MAGIC NUMBERS !
private static readonly int SUCCESS_INDICATOR = 0;
private static readonly int ERROR_INDICATOR = 1;
// TODO DOCUMENT which errorcodes can be expected and what they mean!
public static int Subfunction()
{
int success = SUCCESS_INDICATOR;
try
{
//some code
//some code
}
catch (Exception ex)
{
// TODO write error log!
success = ERROR_INDICATOR;
}
return success;
}
Especially with "C-Guys" on the team you may stumble across this one. (No offense - just my experience)
Or with a state object ...
public static void Mainfunction()
{
try
{
//some code
//some code
ISuccessIndicator success = new ISIImplementation();
Subfunction( success );
if( !succes.HasException )
{
ThirdFunction();
}
else
{
// handle exception from Subfunction
}
}
catch(Exception ex)
{
//write to log
//Exceptions from ThrirdFunction or "else" branch are caught here.
}
}
public static void Subfunction( ISuccessIndicator result )
{
try
{
//some code
//some code
}
catch (Exception ex)
{
result.HasException=true;
result.Exception = ex;
}
}
public interface ISuccessIndicator
{
Exception Exception {get; set;}
bool HasException {get; set;}
}
And if you are really crazy you could ...
public static void Mainfunction()
{
try
{
//some code
//some code
Exception ex = null;
Subfunction( ref ex );
if( ex == null ) // or more modern: ( ex is null )
{
ThirdFunction();
}
else
{
// handle exception from Subfunction
}
}
catch(Exception ex)
{
//write to log
//Exceptions from ThirdFunction or "else" branch caught here.
}
}
public static void Subfunction( ref Exception outEx )
{
try
{
//some code
//some code
}
catch (Exception ex)
{
outEx = ex;
}
}
Please mind, that I in no way would encourage using the latter. But it is possible ... and OP asked for possibilities.
Disclaimer: All snippets untested. Who finds errors can keep them (but please write a comment, so I can fix them).

What's the point of passing ExceptionDispatchInfo around instead of just the Exception?

I understand the value of ExceptionDispatchInfo.Capture(e).Throw() (preserves the original stack trace), but what's the advantage of using Capture early and passing the ExceptionDispatchInfo around vs. just passing the caught Exception around?
As a concrete example, comparing
static Exception CaptureException(Action action)
{
try
{
action();
return null;
}
catch (Exception e)
{
return e;
}
}
public void Test1()
{
ExceptionDispatchInfo.Capture(CaptureException(
() => throw new IOException("Test")))
.Throw();
}
with
static ExceptionDispatchInfo CaptureDispatchInfo(Action action)
{
try
{
action();
return null;
}
catch (Exception e)
{
return ExceptionDispatchInfo.Capture(e);
}
}
public void Test2()
{
CaptureDispatchInfo(() => throw new IOException("Test")).Throw();
}
, both give essentially the same stack traces (It's similar for an async variation of this.). So, I don't really get why the ExceptionDispatchInfo class exists at all, rather than just a combined ExceptionDispatchInfo.Capture(e).Throw() method.
You're assuming that exceptions are immutable. This is not the case - an exception's StackTrace changes when it's re-thrown.
The purpose of ExceptionDispatchInfo.Capture is to capture a potentially mutating exception's StackTrace at a point in time:
void Foo() => throw new InvalidOperationException ("foo");
Exception original = null;
ExceptionDispatchInfo dispatchInfo = null;
try
{
try
{
Foo();
}
catch (Exception ex)
{
original = ex;
dispatchInfo = ExceptionDispatchInfo.Capture (ex);
throw ex;
}
}
catch (Exception ex2)
{
// ex2 is the same object as ex. But with a mutated StackTrace.
Console.WriteLine (ex2 == original); // True
}
// So now "original" has lost the StackTrace containing "Foo":
Console.WriteLine (original.StackTrace.Contains ("Foo")); // False
// But dispatchInfo still has it:
try
{
dispatchInfo.Throw ();
}
catch (Exception ex)
{
Console.WriteLine (ex.StackTrace.Contains ("Foo")); // True
}
ExceptionDispatchInfo is used to preserve the stack trace after an Exception is thrown, allowing you to catch that exception, not throwing it immediately (as part of a catch), and to raise such exception on a later point in the future.
I found a good example of this on
https://thorarin.net/blog/post/2013/02/21/Preserving-Stack-Trace.

How to remove try...catch block from many different functions [duplicate]

This question already has answers here:
Is there a way to catch all unhandled exceptions thrown by a given class?
(6 answers)
Closed 8 years ago.
I have a lot of classes (WCF services) that contain several function. Now I need to handle errors, but I don't want to create a block try ... catch within each function (for error handling).
How can I make try...catch in any class (or something else) so that we catch errors but did not write the same block within each method?
There will always be some duplication of code but you can reduce it to one line
public static class ExceptionHandler
{
public static void Run(Action action)
{
try
{
a();
}
catch(Exception e)
{
//Do Something with your exception here, like logging
}
}
}
and then just call
ExceptionHandler.Run(yourAction);
you can add overloads for functions and what not but this approach is not ideal. As you may want to catch specific exceptions in certain cases.
Since you did not provide code specifically, I will write some sample code to make it more obvious. If you have this:
public class MyClass
{
public void Method1ThatCanThrowException()
{
try
{
// the Method1 code that can throw exception
}
catch (MySpecificException ex)
{
// some specific error handling
}
}
public object Method2ThatCanThrowException()
{
try
{
// the Method2 code that can throw exception
}
catch (MySpecificException ex)
{
// the same specific error handling
}
}
}
So, if you intend to have single place error handling, you can use lambda, and the help of a private method:
private T CheckAndCall<T>(Func<T> funcToCheck)
{
try
{
return funcToCheck();
}
catch (MySpecificException ex)
{
// the old specific error handling
}
}
Notice the use of the Func<T> delegate. This is because you may need to wrap the try-catch logic around some code that can return a value.
Then you can rewrite the above methods like this:
public void Method1ThatCanThrowException()
{
CheckAndCall(
() =>
{
// the Method1 code that can throw exception
return null;
});
}
public object Method2ThatCanThrowException()
{
return CheckAndCall(
() =>
{
// the Method2 code that can throw exception
return someObject;
});
}
For example, rather than having to do this:
public class Program
{
public static string ReadFile(string filename)
{
//A BCL method that throws various exceptions
return System.IO.File.ReadAllText(filename);
}
public static void Main(string[] args)
{
try
{
Console.Write(ReadFile("name.txt"));
}
catch (Exception e)
{
Console.WriteLine("An error occured when retrieving the name! {0}", e.Message);
}
try
{
Console.Write(ReadFile("age.txt"));
}
catch (Exception e)
{
Console.WriteLine("An error occured when retrieving the age! {0}", e.Message);
}
}
}
You could implement a "Try..." method, using the ref or out keyword as appropriate:
public class Program
{
public static bool TryReadFile(string filename, out string val)
{
try
{
val = System.IO.File.ReadAllText(filename);
return true;
}
catch (Exception)
{
return false;
}
}
public static void Main(string[] args)
{
string name, age;
Console.WriteLine(TryReadFile("name.txt", out name) ? name : "An error occured when retrieving the name!");
Console.WriteLine(TryReadFile("age.txt", out age) ? age: "An error occured when retrieving the age!");
}
}
The downside to this approach is that you can't act upon a specific exception, but in the case of simply determining if an operation has or has not succeeded, I find this to be a syntactically clean approach.

Exception casting

I am inserting different message based on the exception type.
I want to insert different custom message into the exception table based on the exception type. I cant use switch statements with exception object.
Any suggestion on how I can do this?
private void ExceptionEngine(Exception e)
{
if (e.)
{
exceptionTable.Rows.Add(null, e.GetType().ToString(), e.Message);
}
if (e is NullReferenceException)
{
...
}
else if (e is ArgumentNullException)
{
...
}
else if (e is SomeCustomException)
{
...
}
else
{
...
}
and inside those if clauses you can cast e to the corresponding exception type to retrieve some specific properties of this exception: ((SomeCustomException)e).SomeCustomProperty
If all the code will be in the if/else blocks then better to use multiple catch (remember to put the most specific types first):
try {
...
} catch (ArgumentNullException e) {
...
} catch (ArgumentException e) { // More specific, this is base type for ArgumentNullException
...
} catch (MyBusinessProcessException e) {
...
} catch (Exception e) { // This needs to be last
...
}
I cant use switch statements with exception object.
If you want to use a switch, you could always use the Typename:
switch (e.GetType().Name)
{
case "ArgumentException" : ... ;
}
This has the possible advantage that you do not match subtypes.
You could unify the handling of different exception types (known at compile time) by a pre-defined dictionary. For example:
// Maps to just String, but you could create and return whatever types you require...
public static class ExceptionProcessor {
static Dictionary<System.Type, Func<String, Exception> sExDictionary =
new Dictionary<System.Type, Func<String, Exception> {
{
typeof(System.Exception), _ => {
return _.GetType().ToString();
}
},
{
typeof(CustomException), _ => {
CustomException tTmp = (CustomException)_;
return tTmp.GetType().ToString() + tTmp.CustomMessage;
}
}
}
public System.String GetInfo(System.Exception pEx) {
return sExDictionary[pEx.GetType()](pEx);
}
}
Usage:
private void ExceptionEngine(Exception e) {
exceptionTable.AddRow(ExceptionProcessor.GetInfo(e));
}

Proper way to find the innermost exception?

I'm working with some classes which, when throwing, have a relatively deep InnerException tree. I'd like to log and act upon the innermost exception which is the one having the real reason for the problem.
I'm currently using something similar to
public static Exception getInnermostException(Exception e) {
while (e.InnerException != null) {
e = e.InnerException;
}
return e;
}
Is this the proper way to handle Exception trees?
I think you can get the innermost exception using the following code:
public static Exception getInnermostException(Exception e) {
return e.GetBaseException();
}
You could use the GetBaseException method.
Very quick example:
try
{
try
{
throw new ArgumentException("Innermost exception");
}
catch (Exception ex)
{
throw new Exception("Wrapper 1",ex);
}
}
catch (Exception ex)
{
// Writes out the ArgumentException details
Console.WriteLine(ex.GetBaseException().ToString());
}
In a word, yes. I cannot think of any significantly better or different way of doing it. Unless you wanted to add it as an extension method instead, but it's really six of one, half-a-dozen of the other.
There are exceptions that can have multiple root causes (e.g. AggregateException and ReflectionTypeLoadException).
I created my own class to navigate the tree and then different visitors to either collect everything or just the root causes. Sample outputs here. Relevant code snippet below.
public void Accept(ExceptionVisitor visitor)
{
Read(this.exception, visitor);
}
private static void Read(Exception ex, ExceptionVisitor visitor)
{
bool isRoot = ex.InnerException == null;
if (isRoot)
{
visitor.VisitRootCause(ex);
}
visitor.Visit(ex);
visitor.Depth++;
bool isAggregateException = TestComplexExceptionType<AggregateException>(ex, visitor, aggregateException => aggregateException.InnerExceptions);
TestComplexExceptionType<ReflectionTypeLoadException>(ex, visitor, reflectionTypeLoadException => reflectionTypeLoadException.LoaderExceptions);
// aggregate exceptions populate the first element from InnerExceptions, so no need to revisit
if (!isRoot && !isAggregateException)
{
visitor.VisitInnerException(ex.InnerException);
Read(ex.InnerException, visitor);
}
// set the depth back to current context
visitor.Depth--;
}
private static bool TestComplexExceptionType<T>(Exception ex, ExceptionVisitor visitor, Func<T, IEnumerable<Exception>> siblingEnumerator) where T : Exception
{
var complexException = ex as T;
if (complexException == null)
{
return false;
}
visitor.VisitComplexException(ex);
foreach (Exception sibling in siblingEnumerator.Invoke(complexException))
{
visitor.VisitSiblingInnerException(sibling);
Read(sibling, visitor);
}
return true;
}

Categories