DependencyProperty定義の記述量削減(F#)
下記記事にてC#でDependencyPropertyの記述量を削減してみました。
DependencyProperty定義の記述量削減 - 何でもプログラミング
今回はF#でDependencyPropertyの記述量を削減してみたいと思います。
内容はほぼAttachedPropertyの時と同じですので、下記記事も参考にしてみてください。
AttachedProperty定義の記述量削減(F#) - 何でもプログラミング
DependencyProperty管理クラス
Register、Get、Set、Changedを管理するクラスになります。
メモリリークしないよう、Changedで利用するEventは、ConditionalWeakTableに配置してあります。
member valで定義されたものは末尾に@が自動で付与されるので、"Property@"となっています。
type DependencyProperty<'owner, 'value when 'owner :> DependencyObject and 'owner : not struct>() = let mutable property : DependencyProperty = null let table = ConditionalWeakTable<'owner, Event<'value>>() member this.Register(?defaultValue : 'value, [<CallerMemberName>]?propertyName : string) = assert (property = null) let name = propertyName.Value.Substring(0, propertyName.Value.Length - "Property@".Length) let metadata = PropertyMetadata(defaultValue |> Option.defaultValue(Unchecked.defaultof<'value>), PropertyChangedCallback(fun obj args -> match table.TryGetValue(obj :?> 'owner) with | true, ev -> ev.Trigger(args.NewValue :?> 'value) | false, _ -> () )) property <- DependencyProperty.Register(name, typeof<'value>, typeof<'owner>, metadata) property member this.Get(obj : 'owner) = obj.GetValue(property) :?> 'value member this.Set(obj : 'owner, value : 'value) = obj.SetValue(property, value) member this.Changed(obj : 'owner) = table.GetOrCreateValue(obj).Publish
利用例
上記クラスを利用すると、下記のようなコードになります。
毎回ownerクラスを指定したくない場合は、一段クラスか関数をかましてください。
type MyControl() as this = inherit UserControl() static let value = DependencyProperty<MyControl, int>() do value.Changed(this).Add( (* 処理 *) ) static member val ValueProperty = value.Register() member this.Value with get() = value.Get(this) and set(x) = value.Set(this, x)