Skip to content

Instantly share code, notes, and snippets.

@Szer
Created December 1, 2018 13:58
Show Gist options
  • Save Szer/a1e4fabfce1d40d6881557c595faa546 to your computer and use it in GitHub Desktop.
Save Szer/a1e4fabfce1d40d6881557c595faa546 to your computer and use it in GitHub Desktop.
open Microsoft.FSharp.Quotations.Patterns
open System.Reflection
let nullTraverse<'a> (expr: Quotations.Expr<'a>) (originObj : obj) : 'a option =
let inline tryGet (p : PropertyInfo) o =
p.GetMethod.Invoke(o,null)
|> Option.ofObj
let rec innerTraverse (nullableObj : obj) = function
| PropertyGet(None, props, _) -> tryGet props obj
| PropertyGet(Some expr, props, _) ->
innerTraverse nullableObj expr
|> Option.bind (tryGet props)
| _ -> failwithf "only get properties are allowed in null traverse"
innerTraverse originObj expr
|> Option.map (fun x -> (x :?> 'a))
let (|NullTraverse|_|) = nullTraverse
type C = { C : obj }
type B = { B : string }
type A = { A : B }
let a = {A = { B = null}}
match a with
| NullTraverse <@a.A.B@> x -> printfn "not null: %A" x
| _ -> printfn "null"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment