Необработанное исключение, поступающее из потока GC при сбое статического конструктора / инициализатора типа

(заголовок был: «TypeLoadException не всегда завернут в TargetInvocationException с использованием Reflection»)

С помощью BLToolkit я выяснил интересный факт - methodInfo.Invoke не всегда ловит исключение в вызывающем методе. So in this sample will be 2 messages - one "handle" and one "unhandle" - seems like Components have different handling inside Reflection on lower levels.

If we comment out method Dispose(bool disposing) - we will receive only "handle" message.

Can anyone give explanation why does it happen and propose a solution? Try-catch inside BLToolkit cannot be marked as answer - I am not member of their team :)

    class Program
{
    static void Main()
    {
        AppDomain.CurrentDomain.UnhandledException +=
            (sender, eventArgs) => Console.WriteLine("unHandled " + eventArgs.ExceptionObject.GetType().FullName);
        try
        {
            try
            {
                var instance = Activator.CreateInstance(typeof(ComponentExecutor));
                MethodInfo mi = typeof(ComponentExecutor).GetMethod("Do");
                BindingFlags bf = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly |
                                  BindingFlags.InvokeMethod;

                mi.Invoke(instance, bf, null, new object[0], CultureInfo.InvariantCulture);
            }
            catch (TargetInvocationException tarEx)
            {
                throw tarEx.InnerException;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Handled " + ex.GetType().FullName);
        }
    }

    class ComponentExecutor
    {
        public void Do()
        {
            new TestComponent().Do();
        }
    }
    class TestComponent : Component
    {
        static TestComponent()
        {
            throw new NullReferenceException();
        }
        [MethodImpl(MethodImplOptions.NoInlining)]
        public void Do()
        {
            Console.WriteLine("Doing");
        }
        protected override void Dispose(bool disposing)
        {
            Console.WriteLine("Disposing");
            base.Dispose(disposing);
        }
    }
}
6
задан Richard 25 January 2011 в 12:29
поделиться