[英]Can't find PropertyGet expression in F# quotation
My goal is to create a function which accepts a generic 'property accesser' function and returns the name of the property it is accessing.我的目标是创建一个 function 接受通用的“属性访问器” function 并返回它正在访问的属性的名称。 For example:例如:
type Person = { Name: string; Age: int }
let blake = { Name = "Blake"; Age = 30 }
let requestedProperty = propertyAccess (fun p -> p.Name) // should return "Name"
I want propertyAccess
to be generic, and to be usable with any type.我希望propertyAccess
是通用的,并且可以用于任何类型。 It might have the signature:它可能有签名:
'T -> 'TProperty -> string
So far, I have tried creating a quotation out of the delegate function and pattern matching the expression tree looking for a PropertyGet
.到目前为止,我已经尝试从委托 function 和模式匹配表达式树中创建一个引用来寻找PropertyGet
。 Unfortunately the quotation expression tree has the shape:不幸的是,引用表达式树的形状是:
NewDelegate (Func`2, delegateArg0,
Application (ValueWithName (<fun:result@88>, f), delegateArg0))
and I'm not able to find the PropertyGet.而且我找不到 PropertyGet。 How can I achieve this?我怎样才能做到这一点?
The entire code looks like:整个代码如下所示:
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"
Thanks谢谢
The problem is that you're simply wrapping a (function) value in a quotation, and the AST ends up being just a ValueWithName
.问题是您只是将(函数)值包装在引号中,而 AST 最终只是一个ValueWithName
。
You want the compiler to automatically quote your argument expression.您希望编译器自动引用您的参数表达式。
type Props =
static member propertyAccess ([<ReflectedDefinition>] expr: Expr<'a -> 'b>) =
match expr with
| Patterns.Lambda(_, Patterns.PropertyGet(_, prop, _)) -> prop.Name
| _ -> failwith "Invalid property"
Note that this will only work on a static member, and not on vals.请注意,这仅适用于 static 成员,不适用于 vals。
let requestedProperty = Props.propertyAccess (fun p -> p.Name) // returns "Name"
You can also consider Expression<Func<T, TValue>>
, which works almost the same.您还可以考虑Expression<Func<T, TValue>>
,它的工作原理几乎相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.