Skip to content

Commit

Permalink
Compile property accessors for PreComputeRecordReader (dotnet#9714)
Browse files Browse the repository at this point in the history
  • Loading branch information
kerams authored and nosami committed Feb 22, 2021
1 parent 67d7fb8 commit 2dfb9b9
Showing 1 changed file with 19 additions and 1 deletion.
20 changes: 19 additions & 1 deletion src/fsharp/FSharp.Core/reflect.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ open Microsoft.FSharp.Core.Operators
open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators
open Microsoft.FSharp.Collections
open Microsoft.FSharp.Primitives.Basics
open System.Linq.Expressions

module internal ReflectionUtils =

Expand Down Expand Up @@ -63,6 +64,19 @@ module internal Impl =
| null -> None
| prop -> Some(fun (obj: obj) -> prop.GetValue (obj, instancePropertyFlags ||| bindingFlags, null, null, null))

let compilePropGetterFunc (prop: PropertyInfo) =
let param = Expression.Parameter (typeof<obj>, "param")

let expr =
Expression.Lambda<Func<obj, obj>> (
Expression.Convert (
Expression.Property (
Expression.Convert (param, prop.DeclaringType),
prop),
typeof<obj>),
param)
expr.Compile ()

//-----------------------------------------------------------------
// ATTRIBUTE DECOMPILATION

Expand Down Expand Up @@ -585,6 +599,10 @@ module internal Impl =
let props = fieldPropsOfRecordType(typ, bindingFlags)
(fun (obj: obj) -> props |> Array.map (fun prop -> prop.GetValue (obj, null)))

let getRecordReaderFromFuncs(typ: Type, bindingFlags) =
let props = fieldPropsOfRecordType(typ, bindingFlags) |> Array.map compilePropGetterFunc
(fun (obj: obj) -> props |> Array.map (fun prop -> prop.Invoke obj))

let getRecordConstructorMethod(typ: Type, bindingFlags) =
let props = fieldPropsOfRecordType(typ, bindingFlags)
let ctor = typ.GetConstructor(BindingFlags.Instance ||| bindingFlags, null, props |> Array.map (fun p -> p.PropertyType), null)
Expand Down Expand Up @@ -806,7 +824,7 @@ type FSharpValue =
static member PreComputeRecordReader(recordType: Type, ?bindingFlags) : (obj -> obj[]) =
let bindingFlags = defaultArg bindingFlags BindingFlags.Public
checkRecordType ("recordType", recordType, bindingFlags)
getRecordReader (recordType, bindingFlags)
getRecordReaderFromFuncs (recordType, bindingFlags)

static member PreComputeRecordConstructor(recordType: Type, ?bindingFlags) =
let bindingFlags = defaultArg bindingFlags BindingFlags.Public
Expand Down

0 comments on commit 2dfb9b9

Please sign in to comment.