繁体   English   中英

在 F# 报价单中找不到 PropertyGet 表达式

[英]Can't find PropertyGet expression in F# quotation

我的目标是创建一个 function 接受通用的“属性访问器” function 并返回它正在访问的属性的名称。 例如:

type Person = { Name: string; Age: int }
let blake = { Name = "Blake"; Age = 30 }

let requestedProperty = propertyAccess (fun p -> p.Name) // should return "Name"

我希望propertyAccess是通用的,并且可以用于任何类型。 它可能有签名:

'T -> 'TProperty -> string

到目前为止,我已经尝试从委托 function 和模式匹配表达式树中创建一个引用来寻找PropertyGet 不幸的是,引用表达式树的形状是:

NewDelegate (Func`2, delegateArg0,
             Application (ValueWithName (<fun:result@88>, f), delegateArg0))

而且我找不到 PropertyGet。 我怎样才能做到这一点?

整个代码如下所示:


let propertyAccess (f: 'T -> 'TProperty) =
    let expression = <@ f @>

    let rec findProperty expr =
        match expr with
        | Application(ex1, ex2) -> findProperty ex1
        | PropertyGet(o, info, lst) -> sprintf "Property: %s" info.Name 
        | Lambda(param, body) -> findProperty body
        | NewDelegate(t, lst, ex) -> findProperty ex
        | ValueWithName(ob, t, s) -> sprintf "ValueName: %s" s
        | _ -> "Couldn't find property"

type Person = { Name: string; Age: int }
let blake = { Name = "Blake"; Age = 30 }

let requestedProperty = propertyAccess (fun p -> p.Name) // should return "Name"

谢谢

问题是您只是将(函数)值包装在引号中,而 AST 最终只是一个ValueWithName

您希望编译器自动引用您的参数表达式。

type Props =
    static member propertyAccess ([<ReflectedDefinition>] expr: Expr<'a -> 'b>) =
      match expr with
      | Patterns.Lambda(_, Patterns.PropertyGet(_, prop, _)) -> prop.Name
      | _ -> failwith "Invalid property"

请注意,这仅适用于 static 成员,不适用于 vals。

let requestedProperty = Props.propertyAccess (fun p -> p.Name) // returns "Name"

您还可以考虑Expression<Func<T, TValue>> ,它的工作原理几乎相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM