これは私が今までに書いたウェットテストコードの一部です。しかし、それは面倒です、便利です。すべての繰り返しの理由は、インターフェイスを流暢に保つためです。私は(この場合はView
であることを起こる)基本クラスを増強した場合、それだけでLabel.Text
プロパティはによって実装されていないためこのF#コードをどのように乾燥させることができますか? (Fluent Interface)
let label = theme.CreateLabel().WithMargin(new Thickness(5.0)).WithText("Hello")
のようなものをやってから私を妨げることになる、View
のインスタンスをバック与えるだろうView
ベースクラス。
ここで私の流暢なインターフェイスです。準備する。それは醜い、そして繰り返します。しかし、それも動作し、使用するのが便利です。
私はそれを乾かす明白な方法がありませんでしたか?
module ViewExtensions =
let private withTwoWayBinding<'TElement, 'TProperty, 'TViewModel, 'TView when 'TView :> IViewFor<'TViewModel>>(viewModel: 'TViewModel, view: 'TView, viewModelProperty: Expr<'TViewModel -> 'TProperty>, viewProperty: Expr<'TView -> 'TProperty>) (element: 'TElement) =
view.Bind(viewModel, ExpressionConversion.toLinq viewModelProperty, ExpressionConversion.toLinq viewProperty) |> ignore
element
let private withHorizontalOptions<'TElement when 'TElement :> View> options (element: 'TElement) =
element.HorizontalOptions <- options
element
let private withVerticalOptions<'TElement when 'TElement :> View> options (element: 'TElement) =
element.VerticalOptions <- options
element
let private withAlignment<'TElement when 'TElement :> View> horizontalOptions verticalOptions (control: 'TElement) =
control |> withHorizontalOptions horizontalOptions |> withVerticalOptions verticalOptions
let private withMargin<'TElement when 'TElement :> View> margin (element: 'TElement) =
element.Margin <- margin
element
let private withActions<'TElement> (actions: ('TElement -> unit)[]) (element: 'TElement) =
for action in actions do action(element)
element
type Xamarin.Forms.Entry with
member this.WithHorizontalOptions(options) = withHorizontalOptions options this
member this.WithVerticalOptions(options) = withHorizontalOptions options this
member this.WithAlignment(horizontalOptions, verticalOptions) = withAlignment horizontalOptions verticalOptions this
member this.WithTwoWayBinding(viewModel, view, viewModelProperty, viewProperty) = withTwoWayBinding(viewModel, view, viewModelProperty, viewProperty) this
member this.WithMargin(margin) = withMargin margin this
member this.With(actions) = withActions actions this
member this.With(action: Entry -> unit) = this.With([|action|])
type Xamarin.Forms.Grid with
member this.WithHorizontalOptions(options) = withHorizontalOptions options this
member this.WithVerticalOptions(options) = withHorizontalOptions options this
member this.WithAlignment(horizontalOptions, verticalOptions) = withAlignment horizontalOptions verticalOptions this
member this.WithMargin(margin) = withMargin margin this
member this.With(actions) = withActions actions this
member this.With(action: Grid -> unit) = this.With([|action|])
type Xamarin.Forms.StackLayout with
member this.WithHorizontalOptions(options) = withHorizontalOptions options this
member this.WithVerticalOptions(options) = withHorizontalOptions options this
member this.WithAlignment(horizontalOptions, verticalOptions) = withAlignment horizontalOptions verticalOptions this
member this.WithMargin(margin) = withMargin margin this
member this.With(actions) = withActions actions this
member this.With(action: StackLayout -> unit) = this.With([|action|])
type Xamarin.Forms.Button with
member this.WithHorizontalOptions(options) = withHorizontalOptions options this
member this.WithVerticalOptions(options) = withHorizontalOptions options this
member this.WithAlignment(horizontalOptions, verticalOptions) = withAlignment horizontalOptions verticalOptions this
member this.WithMargin(margin) = withMargin margin this
member this.WithText(text) = this.Text <- text; this
member this.With(actions) = withActions actions this
member this.With(action: Button -> unit) = this.With([|action|])
type Xamarin.Forms.Switch with
member this.WithHorizontalOptions(options) = withHorizontalOptions options this
member this.WithVerticalOptions(options) = withHorizontalOptions options this
member this.WithAlignment(horizontalOptions, verticalOptions) = withAlignment horizontalOptions verticalOptions this
member this.WithTwoWayBinding(viewModel, view, viewModelProperty, viewProperty) = withTwoWayBinding(viewModel, view, viewModelProperty, viewProperty) this
member this.WithMargin(margin) = withMargin margin this
member this.With(actions) = withActions actions this
member this.With(action: Switch -> unit) = this.With([|action|])
type Xamarin.Forms.Label with
member this.WithHorizontalOptions(options) = withHorizontalOptions options this
member this.WithVerticalOptions(options) = withHorizontalOptions options this
member this.WithAlignment(horizontalOptions, verticalOptions) = withAlignment horizontalOptions verticalOptions this
member this.WithMargin(margin) = withMargin margin this
member this.WithText(text) = this.Text <- text; this
member this.With(actions) = withActions actions this
member this.With(action: Label -> unit) = this.With([|action|])
UPDATE
あなたの助けのおかげので、答えはイエス、私が何かを明らかに行方不明になったています。 TheQuickBrownFoxが説明したように、私は、フォーム
let label = theme.CreateLabel() |> withMargin(new Thickness(5.0)) |> withContent("Hello")
の何かに流れるようなインターフェイスを変更した場合、その後、あなたは上記を参照モンスターは、このコードの削除は確かに非常に喜ばれる
module ViewExtensions =
let withTwoWayBinding<'TElement, 'TProperty, 'TViewModel, 'TView when 'TView :> IViewFor<'TViewModel>>(viewModel: 'TViewModel, view: 'TView, viewModelProperty: Expr<'TViewModel -> 'TProperty>, viewProperty: Expr<'TView -> 'TProperty>) (element: 'TElement) =
view.Bind(viewModel, ExpressionConversion.toLinq viewModelProperty, ExpressionConversion.toLinq viewProperty) |> ignore
element
let withHorizontalOptions options (element: #View) = element.HorizontalOptions <- options; element
let withVerticalOptions options (element: #View) = element.VerticalOptions <- options; element
let withAlignment horizontalOptions verticalOptions element = element |> withHorizontalOptions horizontalOptions |> withVerticalOptions verticalOptions
let withMargin margin (element: #View) = element.Margin <- margin; element
let withCaption text (element: #Button) = element.Text <- text; element
let withText text (element: #Entry) = element.Text <- text; element
let withContent text (element: #Label) = element.Text <- text; element
let withSetUpActions<'TElement> (actions: ('TElement -> unit)[]) (element: 'TElement) = (for action in actions do action(element)); element
let withSetUpAction<'TElement> (action: 'TElement -> unit) = withSetUpActions([|action|])
によって全体を交換することができます。
あなたが行うことはできません拡張メソッドではなく、ポストフィックスアプリケーション(別名「パイプ転送」)ですか?そうすれば、関数を制約付きで汎用にすることができます。 –
私はTheQuickBrownFoxの答えを読むまでは、あなたが何を意味するのかよくわからなかったことを認めなければなりません。今は完璧な意味合いがあります。そしてそれは非常にうまく動作します。更新保留中です。 –