1. 程式人生 > 其它 >dotnet 讀 WPF 原始碼筆記 提升除錯效率的 NamedObject 型別

dotnet 讀 WPF 原始碼筆記 提升除錯效率的 NamedObject 型別

本文來聊聊 WPF 那些值得稱讚的設計中的 NamedObject 型別。在 WPF 中,有很多值得我學習的設計開發思想,其中就包括本文將要介紹的 NamedObject 型別。此型別的定義僅僅只是為了方便除錯,而沒有具體的業務功能

本文來聊聊 WPF 那些值得稱讚的設計中的 NamedObject 型別。在 WPF 中,有很多值得我學習的設計開發思想,其中就包括本文將要介紹的 NamedObject 型別。此型別的定義僅僅只是為了方便除錯,而沒有具體的業務功能

在 WPF 的 WindowsBase 程式集裡面就定義了 WPF 的很多基礎型別,例如咱都在用的 DependencyObject 等型別。本文的 NamedObject 也正是定義在 WindowsBase 程式集裡面眾多的型別之一,程式碼就放在 src\Microsoft.DotNet.Wpf\src\WindowsBase\MS\Internal\NamedObject.cs

檔案裡面

這是一個程式碼量很少的型別,如下面的內容,就是 NamedObject 的全部程式碼

    internal class NamedObject
    {
        public NamedObject(string name)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentNullException(name);

            _name = name;
        }

        public override string ToString()
        {
            if (_name[0] != '{')
            {
                // lazily add {} around the name, to avoid allocating a string
                // until it's actually needed
                _name = String.Format(CultureInfo.InvariantCulture, "{{{0}}}", _name);
            }

            return _name;
        }

        string _name;
    }

按照 dotnet 裡面的常用設計,咱的 ToString 方法大多數都是用來除錯使用,或者序列化使用。而 NamedObject 型別沒有序列化的需求,因此就剩下一個除錯的功能了。可以看到 NamedObject 沒有任何的屬性定義,也沒有任何的方法。實際除了除錯以外,就和 object 物件是一個功能。其實這是對的,這就是專門用來輔助除錯的型別

為什麼需要定義 NamedObject 型別來做除錯輔助?原因是在 WPF 中,有某些地方的邏輯需要用到一個空的 Object 物件,而此物件不是用來做類裡面的內部鎖的資訊,此空物件將會在框架層傳輸。在框架層傳輸一個空的物件無疑會讓開發者在除錯時感覺到無從下手,原因其實和空異常差不多。假定在某個業務邏輯裡面,收到了其他模組發生過來的一個非預期的物件,剛好這個物件是一個空的 object 物件,此時請問這個空的 object 物件是什麼,是由哪個模組建立的

為了構建出一個穩固的 UI 框架,或者為了方便後續像我這樣水平一般的開發者可以參與到框架的開發,古老的 WPF 框架開發大佬們就定義了 NamedObject 物件。如名字一樣,這個型別僅僅只是一個帶命名的 object 物件而已。但一個帶命名的 object 物件就相當於給程式碼加上了單位,可以極大提升框架開發除錯遇到一個空物件時瞭解這是由哪個模組建立的

如 NamedObject 被 DependencyProperty 使用時的例子,在 DependencyProperty 裡面,如果咱有某個未定義的依賴屬性,或者說在繫結或屬性轉換器裡面失敗時返回一個未定義的屬性時,按照最佳實踐,咱應該返回 DependencyProperty 的 UnsetValue 屬性

在其他業務端或 WPF 框架內收到了一個 Object 的時候,如何可以瞭解到這是 DependencyProperty 的 UnsetValue 屬性,而不是開發者使用者在業務層自己建立的某個物件?假定咱的 DependencyProperty 的 UnsetValue 屬性採用空 object 物件,那麼意味著除錯時需要通過 VisualStudio 的建立物件 Id 的功能,通過給 DependencyProperty 的 UnsetValue 屬性建立 Id 才能通過 Id 判斷物件是否相同

無疑,如果只有一次兩次需要如此除錯,那還可以。如果每次除錯框架時都需要執行如上步驟,通過 VisualStudio 的建立物件 Id 的功能才能進行除錯,那小心鍵盤被 WPF 框架開發者砸了

古老的 WPF 框架開發大佬們給 DependencyProperty 的 UnsetValue 屬性的定義如下

   public static readonly object UnsetValue = new NamedObject("DependencyProperty.UnsetValue");

此時的優勢在於當我拿到一個 object 物件的時候,可以在 VisualStudio 裡面快速看到此物件是一個帶命名的 DependencyProperty.UnsetValue 物件,此時就可以快速瞭解到此物件的建立者以及業務意圖

值得我學習的是,不要輕易在對外公開的傳遞的物件,使用 object 物件,而是給此物件一個確切的定義型別。如果可以的話,再給這個確切的定義型別附加一句用來輔助除錯的話,如 "DependencyProperty.UnsetValue" 這個字串。這樣可以方便在框架層進行除錯時,瞭解傳輸的物件的建立者,以及開發者的意圖

當前的 WPF 在 https://github.com/dotnet/wpf 完全開源,使用友好的 MIT 協議,意味著允許任何人任何組織和企業任意處置,包括使用,複製,修改,合併,發表,分發,再授權,或者銷售。在倉庫裡面包含了完全的構建邏輯,只需要本地的網路足夠好(因為需要下載一堆構建工具),即可進行本地構建

部落格園部落格只做備份,部落格釋出就不再更新,如果想看最新部落格,請到 https://blog.lindexi.com/


本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含連結:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。如有任何疑問,請與我[聯絡](mailto:[email protected])。