@@ -10,43 +10,28 @@ open System.Reflection
1010open System.Text .Json .Serialization
1111
1212/// General helper functions and types.
13- module Helpers =
13+ module internal ReflectionHelper =
1414
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
2916
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."
3322
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"
4226
27+ let private listGenericTypeInfo = typedefof<_ list>. GetTypeInfo()
4328 /// <summary>
4429 /// Returns pair of function constructors for `cons(head,tail)` and `nil`
4530 /// used to create list of type <paramref name="t"/> given at runtime.
4631 /// </summary>
4732 /// <param name="t">Type used for result list constructors as type param</param>
4833 let listOfType t =
49- let listType = typedefof <_ list >. GetTypeInfo () .MakeGenericType([| t|]) .GetTypeInfo()
34+ let listType = listGenericTypeInfo .MakeGenericType([| t|]) .GetTypeInfo()
5035 let nil =
5136 let empty = listType.GetDeclaredProperty " Empty"
5237 empty.GetValue ( null )
@@ -67,13 +52,14 @@ module internal ReflectionHelper =
6752 )
6853 array :> obj
6954
55+ let private optionGenericTypeInfo = typedefof<_ option>. GetTypeInfo()
7056 /// <summary>
7157 /// Returns pair of function constructors for `some(value)` and `none`
7258 /// used to create option of type <paramref name="t"/> given at runtime.
7359 /// </summary>
7460 /// <param name="t">Type used for result option constructors as type param</param>
7561 let optionOfType t =
76- let optionType = typedefof <_ option >. GetTypeInfo () .MakeGenericType([| t|]) .GetTypeInfo()
62+ let optionType = optionGenericTypeInfo .MakeGenericType([| t|]) .GetTypeInfo()
7763 let none =
7864 let x = optionType.GetDeclaredProperty " None"
7965 x.GetValue( null )
@@ -101,13 +87,14 @@ module internal ReflectionHelper =
10187 else input
10288 ( some, none, value)
10389
90+ let private valueOptionGenericTypeInfo = typedefof<_ voption>. GetTypeInfo()
10491 /// <summary>
10592 /// Returns pair of function constructors for `some(value)` and `none`
10693 /// used to create option of type <paramref name="t"/> given at runtime.
10794 /// </summary>
10895 /// <param name="t">Type used for result option constructors as type param</param>
10996 let vOptionOfType t =
110- let optionType = typedefof <_ voption >. GetTypeInfo () .MakeGenericType([| t|]) .GetTypeInfo()
97+ let optionType = valueOptionGenericTypeInfo .MakeGenericType([| t|]) .GetTypeInfo()
11198 let none =
11299 let x = optionType.GetDeclaredProperty " None"
113100 x.GetValue( null )
@@ -157,13 +144,14 @@ module internal ReflectionHelper =
157144 else createInclude.Invoke( null , [| value |])
158145 ( `` include `` , skip)
159146
147+ let skippableGenericTypeInfo = typedefof<_ Skippable>. GetTypeInfo()
160148 /// <summary>
161149 /// Returns pair of function constructors for `include(value)` and `skip`
162150 /// used to create option of type <paramref name="t"/> given at runtime.
163151 /// </summary>
164152 /// <param name="t">Type used for result option constructors as type param</param>
165153 let skippableOfType t =
166- let skippableType = typedefof <_ Skippable >. GetTypeInfo () .MakeGenericType([| t|]) .GetTypeInfo()
154+ let skippableType = skippableGenericTypeInfo .MakeGenericType([| t|]) .GetTypeInfo()
167155 let skip =
168156 let x = skippableType.GetDeclaredProperty " Skip"
169157 x.GetValue( null )
@@ -178,3 +166,56 @@ module internal ReflectionHelper =
178166 then value
179167 else createInclude.Invoke( null , [| value |])
180168 ( `` 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