簡體   English   中英

C# - 通過反射 (SetValue()) 調用時無法捕獲屬性設置器中拋出的異常

[英]C# - Exception thrown in property setter cannot be caught when called via reflection (SetValue())

我的問題類似於Using reflection, setter throws exception which can't be caught ,但推薦的解決方案並沒有解決我的問題。

在下面的代碼中,我嘗試通過兩種不同的方式設置類的屬性:第一種,直接,第二種,通過反射。 setter 拋出一個異常(在實際用例中僅當給定值無效時),應該在調用 setter 的地方捕獲該異常。 但是異常只在第一個變體中被捕獲; 在第二個中,catch 塊永遠不會執行。 這是什么原因?

在我的用例中,我想使用反射變體,但程序總是在拋出異常的地方終止,我沒有任何改變來捕獲它。

上面提到的線程建議將調試器配置為在每次異常時中斷(這不可能像第一個變體那樣,異常被完美捕獲)或者異常來自其他地方。 不幸的是,我不知道它會從哪里來。

非常感謝您的幫助!

using System;
using System.Reflection;

namespace ReflectionTestConsole
{
    public class Program
    {
        public static void Main(string[] args)
        {

            Logic logic = new Logic();
            try
            {
                logic.MyProperty = 5;
            } 
            catch(Exception e)
            {   // in this case, the exception is caught here.
                Console.WriteLine("Exception was caught: " + e.Message);
            }

            try{
                PropertyInfo propInfo = logic.GetType().GetProperty("MyProperty");
                propInfo.SetValue(logic,5);
            }
            catch (Exception e)
            {   // in this case, the exception is not caught
                Console.WriteLine(e.Message);
            }

        }
    }

    public class Logic
    {
        private double variable;
        public double MyProperty
        {
            get
            {
                return variable;
            }
            set
            { //Check if value is valid and if not throw an exception
                throw new Exception("This is the exception");
            }
        }
    }
}

使用@Lutti Coelho 和@HimBromBeere 的評論以及此線程,我找到了解決問題的方法:

1)我假設第二個異常(在反射調用中拋出)沒有被捕獲,這是錯誤的。 它被捕獲了,但我的控制台輸出沒有正確顯示它。

2) SetValue()(或 GetValue())反射調用中拋出的每個異常都包含在 TargetInvocationException e 中。 真正的異常是 e.InnerException。 如果您拋出用戶定義的異常並為此特定異常類型編寫 catch 子句,這一點很重要。

理解了這兩件事,代碼在 dotnetfiddle 上按要求運行。 但是,在 Visual Studio 中,調試器仍然在拋出異常時終止,告訴我異常未處理,即使我在反射調用周圍放置了一個 try-catch-block。

3)在這里,提到的線程幫助了我:Visual Studio 有一個名為“Just my Code”的設置(參見工具→選項→調試→常規→啟用我的代碼)。 如果啟用,它會在我的代碼中未處理的每個異常時停止。 在我的例子中,我的代碼拋出了異常,但它讓我的代碼通過 C# 標准反射庫,並且稍后才返回到我的代碼。 由於異常在它離開我的代碼時未得到處理,因此調試器在此時終止。 因此,在 Visual Studio 中禁用此設置最終解決了我的問題。

您的異常被拋出。 但是因為它發生在SetValue方法內部。 異常在InnerException內部。 要獲得特定的異常,您需要調用e.InnerException

    catch (Exception e)
    {   
        Console.WriteLine("Reflection exception was caught: " + e.InnerException.Message);
    }

在簡歷中,您的Exception e是由SetValue方法引發的異常。 由於另一個異常而出現,另一個異常是InnerException

您可以在以下位置看到一個工作示例: https ://dotnetfiddle.net/i49ZQC

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM