Skip to content

Instantly share code, notes, and snippets.

@lust4life
Created December 6, 2017 07:59
Show Gist options
  • Save lust4life/fcfd7d728a0bdf67f6a466f96725a3eb to your computer and use it in GitHub Desktop.
Save lust4life/fcfd7d728a0bdf67f6a466f96725a3eb to your computer and use it in GitHub Desktop.
support custom projection
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
type A = A
with
static member only<'t>(proj: 't -> obj[]) = ()
static member except<'t>(proj: 't -> obj[]) = ()
type Projection =
| Projection of string * How
| NotSupport
and How =
| Only of string list list
| Except of string list list
let rec getNames expr =
match expr with
| Call (_, method, [Lambda( d, NewArray(_, props))]) -> Projection (d.Type.Name, generateNames method.Name props)
| _ -> NotSupport
and generateNames methodName exprs =
exprs
|> List.map (fun expr ->
match expr with
| Coerce (PropertyGet(Some(outterExpr), prop,_), _) -> generateOutter outterExpr [prop.Name]
| _ -> [])
|> fun projs ->
match methodName with
| "only" -> Only projs
| "except" -> Except projs
| _ -> Only []
and generateOutter outterExpr innerProjs =
match outterExpr with
| PropertyGet (Some (expr),prop,_) ->
generateOutter expr (prop.Name :: innerProjs)
| _ -> innerProjs
let exnProjection =
<@@ A.only<Exception>(fun e ->
[|
e.Message;
e.StackTrace;
e.Data;
e.InnerException.Message;
e.InnerException.StackTrace
|]) @@>
let dateExceptCycleReference = <@@ A.except<DateTime>(fun date -> [| date.Date; |]) @@>
getNames dateExceptCycleReference
getNames exnProjection
(*
// output
> getNames dateExceptCycleReference
- ;;
val it : Projection = Projection ("DateTime",Except [["Date"]])
> getNames exnProjection
- ;;
val it : Projection =
Projection
("Exception",
Only
[["Message"]; ["StackTrace"]; ["Data"]; ["InnerException"; "Message"];
["InnerException"; "StackTrace"]])
*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment