Skip to content

Instantly share code, notes, and snippets.

@bleis-tift
Forked from mattpodwysocki/FSharpBinder.fs
Created July 11, 2011 07:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bleis-tift/1075409 to your computer and use it in GitHub Desktop.
Save bleis-tift/1075409 to your computer and use it in GitHub Desktop.
let convert (inp:obj) : 'res =
inp |> unbox
let (?) (o : obj) (s:string) : 'a =
let ty = o.GetType()
let aty = typeof<'a>
if not (FSharpType.IsFunction aty)
then
let cs = CallSite<System.Func<CallSite, obj, obj>>.Create(Binder.GetMember(CSharpBinderFlags.None, s, null, [| CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) |]))
convert (cs.Target.Invoke(cs, o))
else
if not (FSharpType.IsFunction aty) then failwithf "%A is not a function type" aty
let dty,rty = FSharpType.GetFunctionElements aty
let dtys =
if FSharpType.IsTuple dty then FSharpType.GetTupleElements dty
elif dty = typeof<unit> then [| |]
else [|dty|]
let objToObjFunction =
(fun argObj ->
let realArgs =
match dtys with
| [| |] -> [| |]
| [| argTy |] -> [| argObj |]
| argTys ->
assert Microsoft.FSharp.Reflection.FSharpType.IsTuple(argObj.GetType())
Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields(argObj)
let fty = System.Linq.Expressions.Expression.GetFuncType [| yield typeof<CallSite>; yield typeof<obj>; yield! dtys; yield typeof<obj> |]
let cty = typedefof<CallSite<_>>.MakeGenericType [| fty |]
let cs = cty.InvokeMember("Create", BindingFlags.Public ||| BindingFlags.Static ||| BindingFlags.InvokeMethod, null, null, [|(box(Binder.InvokeMember(CSharpBinderFlags.None, s, null, null, Array.create (realArgs.Length + 1) (CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, s)))))|])
|> unbox<CallSite>
let target = cs.GetType().GetField("Target").GetValue(cs)
let res = target.GetType().InvokeMember("Invoke", BindingFlags.Public ||| BindingFlags.Instance ||| BindingFlags.InvokeMethod, null, target, [| yield box cs; yield box o; yield! realArgs |])
res
)
let atyFunction = FSharpValue.MakeFunction(aty,objToObjFunction)
unbox<'a> atyFunction
let (?<-) (o : obj) (s : string) (v : 'a) : unit =
let cs = CallSite<System.Func<CallSite, obj, obj, obj>>.Create(Binder.SetMember(CSharpBinderFlags.None, s, null, [| CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)|]))
cs.Target.Invoke(cs, o, v) |> ignore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment