@@ -10,43 +10,28 @@ open System.Reflection
10
10
open System.Text .Json .Serialization
11
11
12
12
/// General helper functions and types.
13
- module Helpers =
13
+ module internal ReflectionHelper =
14
14
15
- /// Casts a System.Object to a System.Object option.
16
- let optionCast ( value : obj ) =
17
- if isNull value then None
18
- else
19
- let t = value.GetType()
20
- if t.FullName.StartsWith " Microsoft.FSharp.Core.FSharpOption`1" then
21
- let p = t.GetProperty( " Value" )
22
- Some ( p.GetValue( value, [||]))
23
- elif t.FullName.StartsWith " Microsoft.FSharp.Core.FSharpValueOption`1" then
24
- if value = Activator.CreateInstance t then None
25
- else
26
- let p = t.GetProperty( " Value" )
27
- Some ( p.GetValue( value, [||]))
28
- else None
15
+ open Microsoft.FSharp .Quotations .Patterns
29
16
30
- /// Matches a System.Object with an option.
31
- /// If the object is an Option, returns it as Some, otherwise, return None.
32
- let (| ObjectOption | _ |) = optionCast
17
+ let getModuleType quotation =
18
+ match quotation with
19
+ | PropertyGet (_, propertyInfo, _) -> propertyInfo.DeclaringType
20
+ | FieldGet (_, fieldInfo) -> fieldInfo.DeclaringType
21
+ | _ -> failwith " Expression is no property."
33
22
34
- /// Lifts a System.Object to an option, unless it is already an option.
35
- let toOption x =
36
- match x with
37
- | null -> None
38
- | ObjectOption v
39
- | v -> Some v
40
-
41
- module internal ReflectionHelper =
23
+ let [<Literal>] OptionTypeName = " Microsoft.FSharp.Core.FSharpOption`1"
24
+ let [<Literal>] ValueOptionTypeName = " Microsoft.FSharp.Core.FSharpValueOption`1"
25
+ let [<Literal>] SkippableTypeName = " System.Text.Json.Serialization.Skippable`1"
42
26
27
+ let private listGenericTypeInfo = typedefof<_ list>. GetTypeInfo()
43
28
/// <summary>
44
29
/// Returns pair of function constructors for `cons(head,tail)` and `nil`
45
30
/// used to create list of type <paramref name="t"/> given at runtime.
46
31
/// </summary>
47
32
/// <param name="t">Type used for result list constructors as type param</param>
48
33
let listOfType t =
49
- let listType = typedefof <_ list >. GetTypeInfo () .MakeGenericType([| t|]) .GetTypeInfo()
34
+ let listType = listGenericTypeInfo .MakeGenericType([| t|]) .GetTypeInfo()
50
35
let nil =
51
36
let empty = listType.GetDeclaredProperty " Empty"
52
37
empty.GetValue ( null )
@@ -67,13 +52,14 @@ module internal ReflectionHelper =
67
52
)
68
53
array :> obj
69
54
55
+ let private optionGenericTypeInfo = typedefof<_ option>. GetTypeInfo()
70
56
/// <summary>
71
57
/// Returns pair of function constructors for `some(value)` and `none`
72
58
/// used to create option of type <paramref name="t"/> given at runtime.
73
59
/// </summary>
74
60
/// <param name="t">Type used for result option constructors as type param</param>
75
61
let optionOfType t =
76
- let optionType = typedefof <_ option >. GetTypeInfo () .MakeGenericType([| t|]) .GetTypeInfo()
62
+ let optionType = optionGenericTypeInfo .MakeGenericType([| t|]) .GetTypeInfo()
77
63
let none =
78
64
let x = optionType.GetDeclaredProperty " None"
79
65
x.GetValue( null )
@@ -101,13 +87,14 @@ module internal ReflectionHelper =
101
87
else input
102
88
( some, none, value)
103
89
90
+ let private valueOptionGenericTypeInfo = typedefof<_ voption>. GetTypeInfo()
104
91
/// <summary>
105
92
/// Returns pair of function constructors for `some(value)` and `none`
106
93
/// used to create option of type <paramref name="t"/> given at runtime.
107
94
/// </summary>
108
95
/// <param name="t">Type used for result option constructors as type param</param>
109
96
let vOptionOfType t =
110
- let optionType = typedefof <_ voption >. GetTypeInfo () .MakeGenericType([| t|]) .GetTypeInfo()
97
+ let optionType = valueOptionGenericTypeInfo .MakeGenericType([| t|]) .GetTypeInfo()
111
98
let none =
112
99
let x = optionType.GetDeclaredProperty " None"
113
100
x.GetValue( null )
@@ -157,13 +144,14 @@ module internal ReflectionHelper =
157
144
else createInclude.Invoke( null , [| value |])
158
145
( `` include `` , skip)
159
146
147
+ let skippableGenericTypeInfo = typedefof<_ Skippable>. GetTypeInfo()
160
148
/// <summary>
161
149
/// Returns pair of function constructors for `include(value)` and `skip`
162
150
/// used to create option of type <paramref name="t"/> given at runtime.
163
151
/// </summary>
164
152
/// <param name="t">Type used for result option constructors as type param</param>
165
153
let skippableOfType t =
166
- let skippableType = typedefof <_ Skippable >. GetTypeInfo () .MakeGenericType([| t|]) .GetTypeInfo()
154
+ let skippableType = skippableGenericTypeInfo .MakeGenericType([| t|]) .GetTypeInfo()
167
155
let skip =
168
156
let x = skippableType.GetDeclaredProperty " Skip"
169
157
x.GetValue( null )
@@ -178,3 +166,56 @@ module internal ReflectionHelper =
178
166
then value
179
167
else createInclude.Invoke( null , [| value |])
180
168
( `` include `` , skip)
169
+
170
+ module Helpers =
171
+
172
+ let rec internal moduleType = ReflectionHelper.getModuleType <@ moduleType @>
173
+
174
+ /// <summary>
175
+ /// Casts a <see cref="System.Object"/> to a <see cref="option{System.Object}"/>.
176
+ /// </summary>
177
+ let optionCast ( value : obj ) =
178
+ if isNull value then None
179
+ else
180
+ let t = value.GetType()
181
+ if t.FullName.StartsWith ReflectionHelper.OptionTypeName then
182
+ let p = t.GetProperty( " Value" )
183
+ Some ( p.GetValue( value, [||]))
184
+ elif t.FullName.StartsWith ReflectionHelper.ValueOptionTypeName then
185
+ if value = Activator.CreateInstance t then None
186
+ else
187
+ let p = t.GetProperty( " Value" )
188
+ Some ( p.GetValue( value, [||]))
189
+ else None
190
+
191
+ /// <summary>
192
+ /// Matches a System.Object with an option.
193
+ /// If the object is an <see cref="Option{T}", returns it as Some, otherwise, return <see cref="None"/>.
194
+ /// </summary>
195
+ let (| ObjectOption | _ |) = optionCast
196
+
197
+ /// <summary>
198
+ /// Lifts a <see cref="System.Object"/> to an <see cref="option{System.Object}"/>, unless it is already an <see cref="option{System.Object}"/>.
199
+ /// </summary>
200
+ let toOption x =
201
+ match x with
202
+ | null -> None
203
+ | ObjectOption v
204
+ | v -> Some v
205
+
206
+ /// <summary>
207
+ /// Unwraps a <see cref="System.Object"/> from an <see cref="option{System.Object}"/> or <see cref="voption{System.Object}"/>,
208
+ /// unless it is not wrapped.
209
+ /// </summary>
210
+ let unwrap ( value : objnull ) =
211
+ match value with
212
+ | null -> null
213
+ | value ->
214
+ let t = value.GetType()
215
+ if t.FullName.StartsWith ReflectionHelper.OptionTypeName then
216
+ t.GetProperty( " Value" ) .GetValue ( value, [||])
217
+ elif t.FullName.StartsWith ReflectionHelper.ValueOptionTypeName then
218
+ if value = Activator.CreateInstance t then null
219
+ else
220
+ t.GetProperty( " Value" ) .GetValue ( value, [||])
221
+ else value
0 commit comments