2016-08-02 11 views
8

Vì vậy, đây là một số đoạn mã ướt nhất mà tôi từng viết. Nhưng nó rất hữu ích, gây phiền nhiễu. Lý do cho tất cả sự lặp lại là vì tôi muốn giữ giao diện thông thạo. Nếu tôi tăng cường các lớp cơ sở (trong đó sẽ xảy ra là View trong trường hợp này), nó sẽ chỉ trả lại một thể hiện của View, trong đó sẽ ngăn cản tôi làm điều gì đó nhưLàm cách nào để tôi có thể TẮT mã F # này? (Giao diện thông thạo)

let label = theme.CreateLabel().WithMargin(new Thickness(5.0)).WithText("Hello") 

vì tài sản Label.Text không được thực hiện bởi lớp cơ sở View.

Vì vậy, đây là giao diện thông thạo của tôi. Chuẩn bị. Nó xấu xí và lặp đi lặp lại. Nhưng nó cũng hoạt động và thuận tiện để sử dụng.

Tôi đã bỏ lỡ một cách rõ ràng để DỪNG?

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|]) 

CẬP NHẬT

Vì vậy, nhờ sự giúp đỡ của bạn, câu trả lời là có, tôi nhớ da diết cái gì đó rõ ràng. Như TheQuickBrownFox giải thích, nếu tôi thay đổi giao diện thông thạo một cái gì đó có dạng

let label = theme.CreateLabel() |> withMargin(new Thickness(5.0)) |> withContent("Hello") 

sau đó con quái vật mà bạn nhìn thấy ở trên có thể được thay thế hoàn toàn bởi

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|]) 

xóa Mã này là rất hài lòng thực sự.

+2

bạn không thể làm postfix ứng dụng (aka "ống về phía trước") thay vì các phương pháp mở rộng? Bằng cách đó bạn có thể làm cho các hàm chung với các ràng buộc. –

+0

Tôi phải thừa nhận, tôi đã không hoàn toàn chắc chắn những gì bạn có nghĩa là cho đến khi tôi đọc câu trả lời của TheQuickBrownFox. Nó làm cho cảm giác hoàn hảo ngay bây giờ. Và nó hoạt động rất độc đáo. Đang chờ cập nhật. –

Trả lời

11

Các thành ngữ F # cách tiếp cận để giao diện thông thạo là chỉ để sử dụng các đường ống khai thác về phía trước |>

module ViewHelpers 
    let withMargin margin element = ... 
    let withText text element = ... 

open ViewHelpers 

let label = theme.CreateLabel() |> withMargin (new Thickness(5.0)) |> withText "Hello" 

Tôi nghĩ bạn cũng có thể rút ngắn chữ ký chức năng của bạn sử dụng flexible types:

let withMargin margin (element: #View) = ... 
+1

Điều này thật tuyệt vời. Tôi sẽ nhận được vòng để thử nó ra càng sớm càng tốt và đánh dấu đây là câu trả lời nếu mọi việc suôn sẻ. Như thường xảy ra với F #, tôi luôn luôn học hỏi. Các loại linh hoạt là một ý tưởng tuyệt vời, và tôi chưa bao giờ nghe nói về chúng cho đến bây giờ. –

Các vấn đề liên quan