如何使用计算表达式中的自定义操作从构建器访问值

时间:2019-03-17 13:11:29

标签: f# computation-expression

我有一个计算表达式生成器,它接收 建设中的价值

security:
  oauth2:
    client:
      registration:
        google:
          clientId: #############################
          clientSecret: #############################
          redirectUriTemplate: "{baseUrl}/oauth2/callback/{registrationId}"
          scope:
            - email
            - profile
        facebook:
          clientId: ##################
          clientSecret: ###############################
          redirectUriTemplate: "{baseUrl}/oauth2/callback/{registrationId}"
          scope:
            - email
            - public_profile
        github:
          clientId: #######################
          clientSecret: ###########################
          redirectUriTemplate: "{baseUrl}/oauth2/callback/{registrationId}"
          scope:
            - user:email
            - read:user
        linkedin:
          client:
            clientId: ##############
            clientSecret: ##################
            redirectUriTemplate: "{baseUrl}/oauth2/callback/{registrationId}"
            scope: r_liteprofile r_emailaddress
            clientAuthenticatioMethod: POST
      provider:
        facebook:
          authorizationUri: https://www.facebook.com/v3.0/dialog/oauth
          tokenUri: https://graph.facebook.com/v3.0/oauth/access_token
          userInfoUri: https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250)

现在,我想从内部访问值type SomeBuilder<'e> (e: 'e) = member this.Bind(x, fn) = ... member this.Return x = ... member this.ReturnFrom x = ... let buildSome v = SomeBuilder(v) buildSome 2 { return 1 } 通过自定义操作计算表达式,这样

e

所以我真的很想访问基础构建器对象中的属性/值并使用它们

我想我需要类似的东西

buildSome 2 {
    return 1 + e()
}

但这不起作用。

所以我的问题是

a)使用CustomOperations和计算表达式是可能的 b)以及如果可能的话,怎么办?

免责声明:
与编程一样,有一百万种方法可以达到类似的效果 以完全不同的方式。我明确要求这种特殊方式 如果答案只是“否”,我可以。但请避免使用此处列出的最狭义的答案。

2 个答案:

答案 0 :(得分:4)

我不确定您是否喜欢我的答案以及它是否在您的范围之内,但是您可以使用以下技巧捕获构建器实例:

type SomeBuilder<'e> (e: 'e) =
    member this.Value = e

    [<CustomOperation("extract", MaintainsVariableSpaceUsingBind = true, AllowIntoPattern = true)>]
    member this.Extract (state) = this

    member this.Bind(x, fn) = fn x
    member this.Return x  = x
    member this.ReturnFrom x = x


let builder e = new SomeBuilder<_>(e)

let x = builder 1 {
    extract into builder // now we've brought builder in the scope
    printfn "here we can read the value = %d" builder.Value
    return 0
}

答案 1 :(得分:3)

显示主要的构造方法参数在构建器的实例方法的范围内:

type SomeBuilder<'e> (e: 'e) =
    member __.Bind(x, fn) = fn x
    member __.Return x = x
    [<CustomOperation("e", MaintainsVariableSpaceUsingBind = true,  AllowIntoPattern = true)>]
    member __.E _ = e

SomeBuilder 2 {
    e into i
    return 1 + i }
// val it : int = 3
SomeBuilder "bar" {
    e into s
    return "foo" + s }
// val it : string = "foobar"

考虑自定义操作在构建器内部的位置;它将忽略之前的表达式。