かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

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

と表示される。