かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

ポータブルライブラリにもってこいのINotifyPropertyChangedの実装クラス

最近ポータブルライブラリがあついです!何があつくさせるかというと、Microsoft.Bcl.AsyncをNuGetで追加すればasync/awaitが使える上にCallerMemberNameAttributeとかC# 5.0の機能が使えちゃうところですね。しかも以下の幅広いプラットフォームで。

これはもう、ポータブルライブラリに入れれるものはガシガシ入れていくのを今から検討をはじめても早くはないと思います。早くはないと、ちょっと弱気なのはMicrosoft.Bcl.Asyncが、まだ正式リリースじゃないからです。お仕事では使わずにお試し程度に触れておくくらいでちょうどいいのかなと思います。

とりあえず、最初にぱっと思いついたのがINotifyPropertyChangedの実装の基本クラス。こいつは、ポータビリティ抜群ですね。SLでもWPでも.NET FwでもWinRTでも一番よく書かれてるコードの一つだと思います。

using System.ComponentModel;
using System.Runtime.CompilerServices;

public abstract class NotificationObject : INotifyPropertyChanged
{
    protected NotificationObject() { }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var h = this.PropertyChanged;
        if (h != null)
        {
            h(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

これに、Windows ストア アプリのテンプレートで作った時に追加されるBindableBaseのSetPropertyみたいなメソッドも追加してやりましょう。

public abstract class NotificationObject : INotifyPropertyChanged
{
    protected NotificationObject() {}

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var h = this.PropertyChanged;
        if (h != null)
        {
            h(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    protected bool SetProperty<T>(ref T store, T value, [CallerMemberName] string propertyName = null)
    {
        if (Equals(store, value))
        {
            return false;
        }

        store = value;
        this.OnPropertyChanged(propertyName);
        return true;
    }
}

こんなクラスを作っておくと、ポータブルライブラリの対象のバージョンから共通に使えちゃうINotifyPropertyChangedの実装クラスの出来上がり。
小さなことからこつこつとね。

使い方

これでSL4以上, WP7.5以上, .NET 4以上, WinRTでこんなにすっきりとプロパティが定義できちゃいますね!

public class Person : NotificationObject
{
    private string name;
    public string Name
    {
        get { return this.name; }
        set
        {
            this.SetProperty(ref name, value);
        }
    }
}