Cooking with C#
Pages: 1, 2
Recipe 5.6: Handling Exceptions Thrown from Methods Invoked via Reflection
Problem
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.
Solution
The real exception and its information can be obtained through the InnerException property of the TargetInvocationException exception that is thrown by
MethodInfo.Invoke.
Discussion
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 + "\r\n");
if(e.InnerException != null)
{
Console.WriteLine( );
Console.WriteLine("\t**** INNEREXCEPTION START ****");
Console.WriteLine("\tTYPE THAT THREW EXCEPTION: " +
reflectedClass.ToString( ));
Console.WriteLine("\tINNEREXCEPTION MESSAGE: " +
e.InnerException.Message);
Console.WriteLine("\tINNEREXCEPTION SOURCE: " +
e.InnerException.Source);
Console.WriteLine("\tINNEREXCEPTION STACK: " +
e.InnerException.StackTrace);
Console.WriteLine("\tINNEREXCEPTION TARGETSITE: " +
e.InnerException.TargetSite);
Console.WriteLine("\t**** 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:\book cs cookbook\code\test.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 CookBook\code\Test.cs:line 49
at ClassLibrary1.Reflect.TestInvoke( ) in
C:\BOOK CS CookBook\code\Test.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 CookBook\code\Test.cs:line 49
at ClassLibrary1.Reflect.TestInvoke( ) in
C:\BOOK CS CookBook\code\Test.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:\book cs cookbook
\code\test.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.
See Also
See the "Type Class" and "MethodInfo Class" topics in the MSDN documentation.
Be sure to check back to this site in two weeks for more recipes from C# Cookbook. Recipes will cover how to obtain the HTML from a URL, and how to efficiently synchronize the reading and writing of a resource.
Stephen Teilhet has been working with the .NET platform since the pre-alpha version of the.NET 1.0 framework was being developed by Microsoft.
Jay Hilyard has been developing applications for the Windows platform for over 15 years and he currently works on the New Product Team at Newmarket International in Portsmouth, NH.
Return to ONDotnet.com

