I want to make a copy of an object that is of a discriminated union type, with one or two particular fields assigned different values and any other fields copied straight across.
The tricky part is that I'm trying to write a function to do this, that will keep working unchanged even as more cases are added to the union, so I can't use match
; instead, I'm looking for a solution that uses reflection to examine the fields of the particular case. Here's what I have so far on the reverse side, extracting values from an object regardless of its exact type:
let case a =
match FSharpValue.GetUnionFields (a, typeof<Term>) with
| info, _ ->
info
let unpack a =
let fields = List.ofSeq ((case a).GetFields ())
List.collect
(fun (field: PropertyInfo) ->
let t = field.PropertyType
if t = typeof<Term> then
[field.GetValue a :?> Term]
elif t.IsGenericType && t.GenericTypeArguments.[0] = typeof<Term> then
field.GetValue a :?> Term list
else
[]
)
fields
And I'm trying to write a function that starts off something like:
let pack a xs =
let fields = List.ofSeq ((case a).GetFields ())
...
It occurred to me to try to use MemberwiseClone
but that's protected, so can't be used outside subclasses. I'm probably looking for something like 'create a new object of this type, then step through the fields copying across or filling in values as appropriate' though I'm not quite sure what 'this type' would be, since GetType
doesn't work on discriminated unions. What's the best way to go about it?
Aucun commentaire:
Enregistrer un commentaire