Using reflection, you invoke a method that generates an exception. You want to obtain the real exception object and its information in order to diagnose and fix the problem.
The real exception and its information can be obtained through the
InnerException
property of the
TargetInvocationException
exception that is thrown by MethodInfo.Invoke
.
The following example shows how an exception that occurs within a
method invoked via reflection is handled. The
Reflect
class contains a
ReflectionException
method that invokes the static
TestInvoke
method using the reflection classes as
shown here:
using System; using System.Reflection; public class Reflect { public void ReflectionException( ) { Type reflectedClass = typeof(Reflect); try { MethodInfo methodToInvoke = reflectedClass.GetMethod("TestInvoke"); if (methodToInvoke != null) { object oInvoke = methodToInvoke.Invoke(null, null); } } catch(Exception e) { Console.WriteLine("MESSAGE: " + e.Message); Console.WriteLine("SOURCE: " + e.Source); Console.WriteLine("TARGET: " + e.TargetSite); Console.WriteLine("STACK: " + e.StackTrace + " "); if(e.InnerException != null) { Console.WriteLine( ); Console.WriteLine(" **** INNEREXCEPTION START ****"); Console.WriteLine(" TYPE THAT THREW EXCEPTION: " + reflectedClass.ToString( )); Console.WriteLine(" INNEREXCEPTION MESSAGE: " + e.InnerException.Message); Console.WriteLine(" INNEREXCEPTION SOURCE: " + e.InnerException.Source); Console.WriteLine(" INNEREXCEPTION STACK: " + e.InnerException.StackTrace); Console.WriteLine(" INNEREXCEPTION TARGETSITE: " + e.InnerException.TargetSite); Console.WriteLine(" **** INNEREXCEPTION END ****"); } Console.WriteLine( ); // Shows fusion log when assembly cannot be located Console.WriteLine(e.ToString( )); } } // Method to invoke via reflection public static void TestInvoke( ) { throw (new Exception("Thrown from invoked method.")); } }
This code displays the following text:
MESSAGE: Exception has been thrown by the target of an invocation. SOURCE: mscorlib TARGET: System.Object InternalInvoke(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo, Boolean, System.Reflection.Assembly, Boolean) STACK: at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess) at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean verifyAccess) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) at Reflect.ReflectionException( ) in c:ook cs cookbookcode est.cs:line 22 **** INNEREXCEPTION START **** TYPE THAT THREW EXCEPTION: ClassLibrary1.Reflect INNEREXCEPTION MESSAGE: Thrown from invoked method. INNEREXCEPTION SOURCE: ClassLibrary1 INNEREXCEPTION STACK: at ClassLibrary1.Reflect.TestInvoke( ) in C:BOOK CS CookBookCodeTest.cs:line 49 at ClassLibrary1.Reflect.TestInvoke( ) in C:BOOK CS CookBookCodeTest.cs:line 49 INNEREXCEPTION TARGETSITE: Void TestInvoke( ) **** INNEREXCEPTION END ****
When the methodToInvoke.Invoke
method is called,
the TestInvoke
method is called and subsequently
throws an exception. The outer exception thrown is the
TargetInvocationException
exception; this is the
generic exception thrown when a method invoked through reflection
throws an exception. The CLR automatically wraps the original
exception thrown by the invoked method inside of the
TargetInvocationException
object’s InnerException
property.
In this case, the exception thrown by the invoked method is the
generic Exception
exception. This exception is
shown after the section that begins with the text **** INNEREXCEPTION START
****
.
In addition to this text, the code also calls
e.ToString
to print out the exception text. The
text output from ToString
is:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Exception: Thrown from invoked method. at ClassLibrary1.Reflect.TestInvoke( ) in C:BOOK CS CookBookCodeTest.cs:line 49 at ClassLibrary1.Reflect.TestInvoke( ) in C:BOOK CS CookBookCodeTest.cs:line 49 --- End of inner exception stack trace --- at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess) at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean verifyAccess) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) atReflect.ReflectionException( ) in c:ook cs cookbook code est.cs:line 22
Using the ToString
method is a quick and simple
way of displaying the most relevant outer exception information along
with the most relevant information for each inner exception.