My goal is to create a function which accepts a generic 'property accesser' function and returns the name of the property it is accessing. 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. 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
. 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. 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
.
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.
let requestedProperty = Props.propertyAccess (fun p -> p.Name) // returns "Name"
You can also consider Expression<Func<T, TValue>>
, which works almost the same.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.