复制可区分的联合对象
Copying a discriminated union object
我想复制一个可区分联合类型的对象,其中一个或两个特定字段分配了不同的值,而任何其他字段直接复制。
棘手的部分是我正在尝试编写一个函数来执行此操作,即使将更多的案例添加到联合中,它也会保持不变,所以我不能使用 match
;相反,我正在寻找一种使用反射来检查特定案例字段的解决方案。这是我到目前为止在反面所做的,从一个对象中提取值而不管它的确切类型:
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
我正在尝试编写一个函数,它以如下内容开始:
let pack a xs =
let fields = List.ofSeq ((case a).GetFields ())
...
我想尝试使用 MemberwiseClone
但这是受保护的,所以不能在子类之外使用。我可能正在寻找类似 'create a new object of this type, then step through the fields copying across or filling in values as appropriate' 的东西,尽管我不太确定 'this type' 会是什么,因为 GetType
不适用于受歧视的工会。最好的方法是什么?
这实际上比看起来容易得多(忽略反射的常见问题)。
您已经在使用 FSharpValue.GetUnionFields
来获取有关并集案例的信息并获取当前并集的值。还有 FSharpValue.MakeUnion
获取这些信息并为您提供联合值:
type Term =
| Foo of int * string * bool
let a = Foo(42, "answer", false)
let case, values = FSharpValue.GetUnionFields(a, typeof<Term>)
values.[2] <- box true
FSharpValue.MakeUnion(case, values) :?> Term
我想复制一个可区分联合类型的对象,其中一个或两个特定字段分配了不同的值,而任何其他字段直接复制。
棘手的部分是我正在尝试编写一个函数来执行此操作,即使将更多的案例添加到联合中,它也会保持不变,所以我不能使用 match
;相反,我正在寻找一种使用反射来检查特定案例字段的解决方案。这是我到目前为止在反面所做的,从一个对象中提取值而不管它的确切类型:
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
我正在尝试编写一个函数,它以如下内容开始:
let pack a xs =
let fields = List.ofSeq ((case a).GetFields ())
...
我想尝试使用 MemberwiseClone
但这是受保护的,所以不能在子类之外使用。我可能正在寻找类似 'create a new object of this type, then step through the fields copying across or filling in values as appropriate' 的东西,尽管我不太确定 'this type' 会是什么,因为 GetType
不适用于受歧视的工会。最好的方法是什么?
这实际上比看起来容易得多(忽略反射的常见问题)。
您已经在使用 FSharpValue.GetUnionFields
来获取有关并集案例的信息并获取当前并集的值。还有 FSharpValue.MakeUnion
获取这些信息并为您提供联合值:
type Term =
| Foo of int * string * bool
let a = Foo(42, "answer", false)
let case, values = FSharpValue.GetUnionFields(a, typeof<Term>)
values.[2] <- box true
FSharpValue.MakeUnion(case, values) :?> Term