最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#如何正確實(shí)現(xiàn)一個(gè)自定義異常Exception

 更新時(shí)間:2023年09月04日 09:01:59   作者:Agile.Zhou  
這篇文章主要為大家詳細(xì)介紹了C#如何正確實(shí)現(xiàn)一個(gè)自定義異常Exception,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

最近在公司的項(xiàng)目中,編寫(xiě)了幾個(gè)自定義的 Exception 類(lèi)。提交 PR 的時(shí)候,sonarqube 提示這幾個(gè)自定義異常不符合 ISerializable patten. 花了點(diǎn)時(shí)間稍微研究了一下,把這個(gè)問(wèn)題解了。今天在此記錄一下,可能大家都會(huì)幫助到大家。

自定義異常

編寫(xiě)一個(gè)自定義的異常,繼承自 Exception,其中定義一個(gè) ErrorCode 來(lái)存儲(chǔ)異常編號(hào)。平平無(wú)奇的一個(gè)類(lèi),太常見(jiàn)了。大家覺(jué)得有沒(méi)有什么問(wèn)題?

    [Serializable]
    public class MyException : Exception
    {
        public string ErrorCode { get;}
        public MyException(string message, string errorCode) : base(message)
        {
            ErrorCode = errorCode;
        }
    }

如我們對(duì)這個(gè)異常編寫(xiě)一個(gè)簡(jiǎn)單的單元測(cè)試。步驟如下:

        [TestMethod()]
        public void MyExceptionTest()
        {
            // arrange
            var orignalException = new MyException("Hi", "1000");
            var bf = new BinaryFormatter();
            var ms = new MemoryStream();
            // act
            bf.Serialize(ms, orignalException);
            ms.Seek(0, 0);
            var newException = bf.Deserialize(ms) as MyException;
            // assert
            Assert.AreEqual(orignalException.Message, newException.Message);
            Assert.AreEqual(orignalException.ErrorCode, newException.ErrorCode);
        }

這個(gè)測(cè)試主要是對(duì)一個(gè) MyException 的實(shí)例使用 BinaryFormatter 進(jìn)行序列化,然后反序列化成一個(gè)新的對(duì)象。將新舊兩個(gè)對(duì)象的 ErrorCode 跟 Message 字段進(jìn)行斷言,也很簡(jiǎn)單。

讓我們運(yùn)行一下這個(gè)測(cè)試,很可惜失敗了。測(cè)試用例直接拋了一個(gè)異常,大概是說(shuō)找不到序列化構(gòu)造器。

Designing Custom Exceptions Guideline

簡(jiǎn)單的搜索了一下,發(fā)現(xiàn)微軟有對(duì)于自定義 Exception 的Designing Custom Exceptions。

總結(jié)一下大概有以下幾點(diǎn):

  • 一定要從 System.Exception 或其他常見(jiàn)基本異常之一派生異常。
  • 異常類(lèi)名稱(chēng)一定要以后綴 Exception 結(jié)尾。
  • 應(yīng)使異??尚蛄谢?異常必須可序列化才能跨越應(yīng)用程序域和遠(yuǎn)程處理邊界正確工作。
  • 一定要在所有異常上都提供(至少是這樣)下列常見(jiàn)構(gòu)造函數(shù)。 確保參數(shù)的名稱(chēng)和類(lèi)型與在下面的代碼示例中使用的那些相同。
public class NewException : BaseException, ISerializable
{
    public NewException()
    {
        // Add implementation.
    }
    public NewException(string message)
    {
        // Add implementation.
    }
    public NewException(string message, Exception inner)
    {
        // Add implementation.
    }
    // This constructor is needed for serialization.
   protected NewException(SerializationInfo info, StreamingContext context)
   {
        // Add implementation.
   }
}

按照上面的 guideline 重新改一下我們的 MyException,主要是添加了幾個(gè)構(gòu)造器。修改后的代碼如下:

    [Serializable]
    public class MyException : Exception
    {
        public string ErrorCode { get; }
        public MyException()
        {
        }
        public MyException(string message, string errorCode) : base(message)
        {
            ErrorCode = errorCode;
        }
        public MyException(string message, Exception inner): base(message, inner)
        {
        }
        protected MyException(SerializationInfo info, StreamingContext context)
        {
        }
    }

很可惜按照微軟的 guideline 單元測(cè)試還是沒(méi)通過(guò)。獲取 Message 字段的時(shí)候會(huì)直接 throw 一個(gè) Exception。

那么到底該怎么實(shí)現(xiàn)呢?

正確的方式

我們還是按照微軟 guideline 進(jìn)行編寫(xiě),但是在序列化構(gòu)造器的上調(diào)用 base 的構(gòu)造器。并且 override 基類(lèi)的 GetObjectData 方法。

    [Serializable]
    public class MyException : Exception
    {
        public string ErrorCode { get; }
        public MyException()
        {
        }
        public MyException(string message, string errorCode) : base(message)
        {
            ErrorCode = errorCode;
        }
        public MyException(string message, Exception inner): base(message, inner)
        {
        }
        protected MyException(SerializationInfo info, StreamingContext context): base(info, context)
        {
            // Set the ErrorCode value from info dictionary.
            ErrorCode = info.GetString("ErrorCode");
        }
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (!string.IsNullOrEmpty(ErrorCode))
            {
                // Add the ErrorCode to the SerializationInfo dictionary.
                info.AddValue("ErrorCode", ErrorCode);
            }
            base.GetObjectData(info, context);
        }
    }

在序列化構(gòu)造器里從 SerializationInfo 對(duì)象里恢復(fù) ErrorCode 的值。調(diào)用 base 的構(gòu)造可以確?;?lèi)的 Message 字段被正確的還原。這里與其說(shuō)是序列化構(gòu)造器不如說(shuō)是反序列化構(gòu)造器,因?yàn)檫@個(gè)構(gòu)造器會(huì)在反序列化恢復(fù)成對(duì)象的時(shí)候被調(diào)用。

   protected MyException(SerializationInfo info, StreamingContext context): base(info, context)
        {
            // Set the ErrorCode value from info dictionary.
            ErrorCode = info.GetString("ErrorCode");
        }

這個(gè) GetObjectData 方法是 ISerializable 接口提供的方法,所以基類(lèi)里肯定有實(shí)現(xiàn)。我們的子類(lèi)需要 override 它。把自己需要序列化的字段添加到 SerializationInfo 對(duì)象中,這樣在上面反序列化的時(shí)候確??梢园炎侄蔚闹到o恢復(fù)回來(lái)。記住不要忘記調(diào)用 base.GetObjectData(info, context), 確?;?lèi)的字段數(shù)據(jù)能正確的被序列化。

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (!string.IsNullOrEmpty(ErrorCode))
            {
                // Add the ErrorCode to the SerializationInfo dictionary.
                info.AddValue("ErrorCode", ErrorCode);
            }
            base.GetObjectData(info, context);
        }

再次運(yùn)行單元測(cè)試,這次順利的通過(guò)了,說(shuō)明 Message 跟 ErrorCode 字段在反序列化后成功的被恢復(fù)了。

總結(jié)

自定義異常是大家日常編碼過(guò)程中非常常見(jiàn)的操作。但是看來(lái)要寫(xiě)好一個(gè)自定義異常類(lèi)也不是那么簡(jiǎn)單??偨Y(jié)一下需要注意以下幾點(diǎn):

  • 添加 [Serializable] Attribute
  • 遵守微軟的 guideline,特別是構(gòu)造器部分 Designing Custom Exceptions Guideline
  • 在序列化構(gòu)造器對(duì)字段值進(jìn)行恢復(fù),不要忘記調(diào)用基類(lèi)的序列化構(gòu)造器
  • 重寫(xiě) GetObjectData 方法,把需要序列化的字段添加到 SerializationInfo 對(duì)象上,同樣不要忘記調(diào)用基類(lèi)的 GetObjectData這個(gè)問(wèn)題雖然在自定義 Exception 上暴露出來(lái),其實(shí)可以推廣到所有實(shí)現(xiàn) ISerializable 接口的類(lèi)都需要注意 3,4 兩點(diǎn)。

以上就是C#如何正確實(shí)現(xiàn)一個(gè)自定義異常Exception的詳細(xì)內(nèi)容,更多關(guān)于C#自定義異常的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

柘城县| 平山县| 凌海市| 巴彦县| 奉贤区| 新巴尔虎左旗| 南郑县| 梁河县| 正安县| 旌德县| 寿阳县| 呼图壁县| 吉木萨尔县| 婺源县| 宁武县| 仁化县| 河北省| 柘荣县| 临沧市| 公主岭市| 江华| 平果县| 杂多县| 沂南县| 南雄市| 老河口市| 理塘县| 长海县| 长岛县| 临沭县| 利川市| 岑溪市| 雅安市| 光山县| 周口市| 金门县| 靖安县| 邓州市| 诸暨市| 长汀县| 石柱|