かずきのBlog@hatena

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

F#版のBindableBaseクラス

F#でINotifyPropertyChangedを実装するとどうなるかな~というので実装してみた。

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
open Microsoft.FSharp.Quotations.DerivedPatterns

type BindableBase() =
    let propertyChnged = Event<_, _>()
    interface System.ComponentModel.INotifyPropertyChanged with
        [<CLIEventAttribute>]
        member x.PropertyChanged = propertyChnged.Publish

    member x.Set<'T>((field: 'T byref), value, propertyExpression) =
        if (System.Object.Equals(field, value)) then
            false
        else
            field <- value

            match propertyExpression with
            | PropertyGet(_, info, _) -> propertyChnged.Trigger(x, System.ComponentModel.PropertyChangedEventArgs(info.Name))
            | _ -> ()

            true

SetメソッドのpropertyExpressionは、F#のコード クォート (F#)を使ってタイプセーフにプロパティ名を指定できるようにしてみました。使い方はこんな感じ。

type Person() =
    inherit BindableBase()

    let mutable name =""
    member this.Name 
        with get() = name
        and set(v) = this.Set(&name, v, <@ this.Name @>) |> ignore
let p = Person()
(p :> System.ComponentModel.INotifyPropertyChanged).PropertyChanged.Add(fun e -> printfn "%s" e.PropertyName)
p.Name <- "aaa"
printfn "%s" p.Name

実行すると

Name
aaa

と表示される。