.NET 4.5(C#):INotifyPropertyChanged執行的演變:從運算式樹狀架構到調用方資訊的BindableBase類型

來源:互聯網
上載者:User

INotifyPropertyChanged介面,任何WPF、Silverlight甚至是未來WinRT程式員都必須知道的類型。執行上不用多說,建立一個PropertyChangedEventArgs,資料是屬性的名稱。隨著MVVM模式的大範圍應用,讓人們不得重新審視INotifyPropertyChanged的執行方式(因為MVVM中的ViewModel通常是執行INotifyPropertyChanged的),顯然,最簡單的執行方式很不雅觀,如下:

string companyName;

public string CompanyName

{

    get { return companyName; }

    set

    {

        if (value != companyName)

        {

            companyName = value;

            //調用PropertyChanged事件

            OnPropertyChanged("CompanyName");

        }

    }

}

 

於是.NET 3.5後,運算式樹狀架構(Expression Tree)出現帶來了另一種方式,不管你怎樣看待這種方法,但至少開發人員不需要自己定義一個字串代表屬性名稱,此項工作交給了Expression Tree。

這個改進的方法也是比較流行的,比如微軟的Prism架構中的NotificationObject就是這樣做的,Prism中的PropertySupport.ExtractPropertyName<T>方法可以提取運算式樹狀架構中的MemberExpression,並返回PropertyInfo的Name屬性,這樣開發人員只需要定義一個返回指定屬性的Expression Tree(通過Lambda運算式)。

 

還有一些工程中有ViewModelEx的類型和上述功能也是類似的。

比如:

//繼承Prism中的NotificationObject,後者執行INotifyPropertyChanged

class MyViewModel : NotificationObject

{

    private bool _TaskFinished;

    public bool TaskFinished

    {

        get { return _TaskFinished; }

        set

        {

            if (value != _TaskFinished)

            {

                _TaskFinished = value;

                //通過定義Expression Tree,最終提取屬性名稱

                RaisePropertyChanged<bool>(() => TaskFinished);

            }

        }

    }

}

 

終於到了.NET 4.5,微軟對此進行了直接的改進(要知道Expression Tree的直接意圖並不是直接針對此的),.NET 4.5中加入了調用者資訊,具體是如下三個屬性類別型:

CallerMemberName, CallerFilePath, CallerLineNumber。全部在System.Runtime.CompilerServices命名空間內。

分別對應調用方成員名稱,原始碼檔案路徑和原始碼行。

 

注意不要把調用資訊想象成什麼很神奇的東西,實際上僅僅是編譯中把相應資訊作為常量傳入到參數中,因此調用資訊只能用在具有預設值的方法參數上。

代碼:

//+ using System.Runtime.CompilerServices;

class Program

{

    static void Main(string[] args)

    {

        doo();

    }

 

    static void doo([CallerMemberName]string member = null,

        [CallerFilePath] string path = null,

        [CallerLineNumber] int line = 0)

    {

        Console.WriteLine("調用我的是:檔案:{0},行數:{1},成員名稱:{2}"

            , path, member, line);

    }

}

 

輸出:

調用我的是:檔案:c:\Users\Mgen\Documents\Visual Studio 2012\Projects\Mgen\Mgen\

Program.cs,行數:Main,成員名稱:15

 

CallerMemberName很智能,當在屬性中調用時,返回的是屬性名稱而不是屬性包裝的背後方法,否則CallerMemberName就沒用了呵呵。

那麼我們可以這樣定義OnPropertyChanged方法,使用CallerMemberName特性:

protected void OnPropertyChanged([CallerMemberName] string propertyName = null)

{

    var eventHandler = this.PropertyChanged;

    if (eventHandler != null)

    {

        eventHandler(this, new PropertyChangedEventArgs(propertyName));

    }

}

 

接著在屬性的set中直接調用,因為有了CallerMemberName特性,根本不需要任何參數,編譯器會傳入相應的參數,如下:

private int myVar;

public int MyProperty

{

    get { return myVar; }

    set

    {

        if (myVar != value)

        {

            myVar = value;

            OnPropertyChanged();

        }

    }

}

 

這還沒有完,微軟既然決定好好改進一下,就不會這樣就完了,Visual Studio 2012的Metro應用程式工程中的Common檔案夾中有一個BindableBase類型,必須先繼承INotifyPropertyChanged:

public abstract class BindableBase : INotifyPropertyChanged

 

他不僅有上面那個OnPropertyChanged方法,還有一個SetProperty方法:

protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)

{

    if (object.Equals(storage, value)) return false;

 

    storage = value;

    this.OnPropertyChanged(propertyName);

    return true;

}

 

就是set中常見的判斷值的邏輯,那麼有了BindableBase,最後的INotifyPropertyChanged執行就是這樣:

class Mgen : BindableBase

{

    private int myVar;

    public int MyProperty

    {

        get { return myVar; }

        set { SetProperty(ref myVar, value); }

    }

}

怎麼樣?碉堡了,我認為。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.