rwa*_*ace 0 reflection f# discriminated-union
我想制作一个具有区别联合类型的对象的副本,其中一个或两个特定字段分配不同的值,并且任何其他字段直接复制.
棘手的部分是我正在尝试编写一个函数来执行此操作,即使将更多情况添加到联合中,这将保持工作不变,因此我无法使用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
Run Code Online (Sandbox Code Playgroud)
而我正在尝试编写一个类似于以下内容的函数:
let pack a xs =
let fields = List.ofSeq ((case a).GetFields ())
...
Run Code Online (Sandbox Code Playgroud)
我MemberwiseClone
想到尝试使用它但受保护,所以不能在子类之外使用.我可能正在寻找类似'创建这种类型的新对象,然后逐步复制字段或填写适当的值',尽管我不太确定'这种类型'会是什么,因为GetType
不是从事歧视性工会的工作.什么是最好的方法呢?
这实际上比看起来容易得多(忽略了反射的常见问题).
您已经在使用FSharpValue.GetUnionFields
获取有关union案例的信息并获取当前union的值.还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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
124 次 |
最近记录: |