@@ -6,16 +6,26 @@ open FSharp.Reflection
66open System.Reflection .Emit
77open System.Text .Json
88
9- type internal Serializer = delegate of Utf8JsonWriter * obj * JsonSerializerOptions -> unit
10- type internal Deserializer = delegate of byref < Utf8JsonReader > * obj * JsonSerializerOptions -> unit
9+ type internal Serializer = Action< Utf8JsonWriter, obj, JsonSerializerOptions>
10+
11+ type internal RefobjFieldSetter < 'Record , 'Field > = Action< 'Record, 'Field>
12+ type internal StructFieldSetter < 'Record , 'Field > = delegate of byref < 'Record > * 'Field -> unit
13+
14+ type internal RefobjDeserializer < 'Record > = delegate of byref < Utf8JsonReader > * 'Record * JsonSerializerOptions -> unit
15+ type internal StructDeserializer < 'Record > = delegate of byref < Utf8JsonReader > * byref < 'Record > * JsonSerializerOptions -> unit
16+
17+ [<Struct>]
18+ type internal Deserializer < 'Record > =
19+ | DStruct of s : StructDeserializer<'Record>
20+ | DRefobj of n : RefobjDeserializer<'Record>
1121
1222type internal RecordField < 'Record > =
1323 {
1424 Name: string
1525 Type: Type
1626 Ignore: bool
1727 Serialize: Serializer
18- Deserialize: Deserializer
28+ Deserialize: Deserializer < 'Record >
1929 }
2030
2131module internal RecordReflection =
@@ -30,27 +40,39 @@ module internal RecordReflection =
3040 |> Array.isEmpty
3141 |> not
3242
33- let private deserializer < 'Field > ( f : FieldInfo ) =
43+ let private deserializer < 'Record , ' Field> ( f : FieldInfo ) =
3444 let setter =
3545 let dynMethod =
3646 new DynamicMethod(
3747 f.Name,
3848 typeof< Void>,
39- [| typeof< obj>; f.FieldType |],
49+ [|
50+ ( if f.DeclaringType.IsValueType
51+ then typeof< 'Record>. MakeByRefType()
52+ else typeof< 'Record>)
53+ f.FieldType
54+ |],
4055 typedefof< RecordField<_>>. Module,
4156 skipVisibility = true
4257 )
4358 let gen = dynMethod.GetILGenerator()
4459 gen.Emit( OpCodes.Ldarg_ 0)
45- if f.DeclaringType.IsValueType then
46- gen.Emit( OpCodes.Unbox, f.DeclaringType)
4760 gen.Emit( OpCodes.Ldarg_ 1)
4861 gen.Emit( OpCodes.Stfld, f)
4962 gen.Emit( OpCodes.Ret)
50- dynMethod.CreateDelegate( typeof< Action< obj, 'Field>>) :?> Action< obj, 'Field>
51- Deserializer( fun reader record options ->
52- let value = JsonSerializer.Deserialize< 'Field>(& reader, options)
53- setter.Invoke( record, value))
63+ dynMethod
64+ if f.DeclaringType.IsValueType then
65+ let setter = setter.CreateDelegate( typeof< StructFieldSetter< 'Record, 'Field>>) :?> StructFieldSetter< 'Record, 'Field>
66+ StructDeserializer< 'Record>( fun reader record options ->
67+ let value = JsonSerializer.Deserialize< 'Field>(& reader, options)
68+ setter.Invoke(& record, value))
69+ |> DStruct
70+ else
71+ let setter = setter.CreateDelegate( typeof< RefobjFieldSetter< 'Record, 'Field>>) :?> RefobjFieldSetter< 'Record, 'Field>
72+ RefobjDeserializer< 'Record>( fun reader record options ->
73+ let value = JsonSerializer.Deserialize< 'Field>(& reader, options)
74+ setter.Invoke( record, value))
75+ |> DRefobj
5476
5577 let private serializer < 'Field > ( f : FieldInfo ) =
5678 let getter =
@@ -89,9 +111,9 @@ module internal RecordReflection =
89111 :?> Serializer
90112 let deserializer =
91113 thisModule.GetMethod( " deserializer" , BindingFlags.Static ||| BindingFlags.NonPublic)
92- .MakeGenericMethod( p.PropertyType)
114+ .MakeGenericMethod( recordTy , p.PropertyType)
93115 .Invoke( null , [| f|])
94- :?> Deserializer
116+ :?> Deserializer< 'Record >
95117 {
96118 Name = name p
97119 Type = p.PropertyType
0 commit comments