特にオプションを指定せずにType.InvokeMemberメソッドやMethodInfo.Invokeメソッドなどによってメンバを呼び出し、呼び出した先で例外が発生した場合、その例外はTargetInvocationExceptionにラップされた上でスローされます。
BindingFlags.DoNotWrapExceptionsを指定することにより、発生した例外をTargetInvocationExceptionにラップしないようにすることができます。 これにより、発生した例外そのものを捕捉できるようになります。 DoNotWrapExceptions
は.NET Standard 2.1/.NET Core 2.1以降で使用することができます。
BindingFlags.DoNotWrapExceptionsを指定して例外をそのままでスローさせる .NET Standard 2.1/.NET Core 2.1
using System;
using System.Reflection;
class C {
public void M() => throw new NotImplementedException();
}
class Sample {
static void Main()
{
var t = typeof(C);
var inst = Activator.CreateInstance(t);
var m = t.GetMethod("M");
try {
// MethodInfo.Invokeを使ってメソッドを呼び出す
// BindingFlags.DoNotWrapExceptionsを指定することにより、
// 発生した例外をTargetInvocationExceptionにラップさせず、そのままでスローさせる
m.Invoke(inst, BindingFlags.DoNotWrapExceptions, parameters: null, binder: null, culture: null);
}
catch (NotImplementedException ex) {
Console.WriteLine(ex); // メソッドがスローする例外がそのまま捕捉される
}
catch (TargetInvocationException ex) {
Console.WriteLine(ex); // TargetInvocationExceptionはスローされないので、ここでは捕捉されない
}
}
}
実行結果
System.NotImplementedException: The method or operation is not implemented. at C.M() 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 Sample.Main()