例外TargetInvocationExceptionは、Type.InvokeMemberメソッドやMethodInfo.InvokeメソッドなどMemberInfo派生クラスを介したメンバ呼び出しの際に、呼び出し先で例外が発生した場合にスローされる例外です。
呼び出したメンバで発生した例外は、TargetInvocationExceptionにラップされた上で再スローされます。 実際にメンバがスローした例外は、キャッチした例外のInnerExceptionプロパティを参照することで取得することができます。
Type.InvokeMemberを介した呼び出しでメソッドがスローした例外をキャッチする
Imports System
Imports System.Reflection
Class C
Public Sub M()
Throw New NotImplementedException()
End Sub
End Class
Class Sample
Shared Sub Main()
Dim t As Type = GetType(C)
Dim inst As Object = Activator.CreateInstance(t)
Try
' Type.InvokeMemberを使ってメソッドを呼び出す (呼び出し先で例外が発生する)
t.InvokeMember("M", BindingFlags.InvokeMethod, Nothing, inst, Nothing)
' 呼び出したメソッドで例外が発生した場合、TargetInvocationExceptionがスローされる
Catch ex As TargetInvocationException
Console.WriteLine(ex)
Console.WriteLine()
' InnerExceptionプロパティを参照してメソッドが実際にスローした例外を取得する
Console.WriteLine("actual exception type: {0}", ex.InnerException.GetType())
End Try
End Sub
End Class
実行結果
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NotImplementedException: The method or operation is not implemented. at C.M() --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args) at Sample.Main() actual exception type: System.NotImplementedException
MethodInfo.Invokeのほかにも、PropertyInfo.GetValue/SetValueやConstructorInfo.Invokeによってプロパティやコンストラクタなどを呼び出した結果例外が発生した場合も、同様にTargetInvocationExceptionがスローされます。
なお、BindingFlags.DoNotWrapExceptionsを指定することにより、例外が発生した場合でもTargetInvocationExceptionにラップさせず、発生した例外そのものをキャッチすることもできます。