Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reflection 检索F中记录字段的值时获取可选类型的值#_Reflection_F#_Record - Fatal编程技术网

Reflection 检索F中记录字段的值时获取可选类型的值#

Reflection 检索F中记录字段的值时获取可选类型的值#,reflection,f#,record,Reflection,F#,Record,我有一个定义如下的类型: type Employee = { Id: Guid Name: string Phone: string Email: Option<string> } 我想使用反射从该记录类型中提取字段名和值,如下所示: let getFieldValueMappingOfARecordType (data: 'T) : seq<string * obj> = let fieldValueMapping =

我有一个定义如下的类型:

type Employee = {
    Id:    Guid
    Name:  string
    Phone: string
    Email: Option<string>
}
我想使用反射从该记录类型中提取字段名和值,如下所示:

let getFieldValueMappingOfARecordType (data: 'T) : seq<string * obj> =
    let fieldValueMapping =
        data.GetType()
        |> FSharpType.GetRecordFields
        |> Seq.map (
            fun propertyInfo ->

                    (propertyInfo.Name, data |> propertyInfo.GetValue)
        )
    fieldValueMapping
let emp = {
    Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
    Name = "A"
    Phone = "B"
    Email = None
}
给了我们:

val mapping : (string * obj) list =
  [("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
   ("Email", Some "E")]
到目前为止,它在非可选类型下运行良好。但对于可选类型,它将字段的值返回为
Some value
None
。我想做的是,当字段具有
某些值时,获取
,或者当字段为
无时,将其设置为
null

基本上如下所示:

val mapping : (string * obj) list =
  [("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
   ("Email", "E")]
或者,如果employee实例如下所示:

let getFieldValueMappingOfARecordType (data: 'T) : seq<string * obj> =
    let fieldValueMapping =
        data.GetType()
        |> FSharpType.GetRecordFields
        |> Seq.map (
            fun propertyInfo ->

                    (propertyInfo.Name, data |> propertyInfo.GetValue)
        )
    fieldValueMapping
let emp = {
    Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
    Name = "A"
    Phone = "B"
    Email = None
}
那么

这是我到目前为止所拥有的(非工作代码):

开放系统
打开Microsoft.FSharp.Reflection
开放系统。反射
员工类型={
Id:Guid
名称:string
电话:string
电子邮件:选项
}
设emp={
Id=Guid“bc07e94c-b376-45a2-928b-508B88002C9”
Name=“A”
Phone=“B”
电子邮件=一些“E”
}
let getSomeOrNull(t:类型)(o:对象)=
让opt=typedefof.MakeGenericType[| t |]
将(o:?>opt)与
|一些s->
s
|无->
无效的
让getValues(数据:'T)=
让价值观=
data.GetType()
|>FSharpType.GetRecordFields
|>Array.map(
趣味房产信息->
让值=
数据|>propertyInfo.GetValue
let等值线=
propertyInfo.PropertyType.IsGenericType&&propertyInfo.PropertyType.GetGenericTypeDefinition()=typedefof
将等厚线与
|正确->
(propertyInfo.Name,(getSomeOrNull propertyInfo.PropertyType值))
|错误->
(propertyInfo.Name,value)
)
价值观
getValues emp
|>printfn“%A”

我认为实现这一点的唯一方法是使用反射:

let getSomeOrNull (t: Type) (o: obj) =
    if isNull o then null
    else t.GetProperty("Value").GetValue(o)

我认为这应该起作用:

let getSomeOrNull (o: obj) =
    match o with
    | :? Option<string> as o -> a |> Option.toObj > box
    | _ -> null
让getSomeOrNull(o:obj)=
匹配
| :? 选项为o->a |>Option.toObj>框
|->null

Solo。。。您现有的解决方案有什么问题?问题是我不知道如何将对象类型强制转换为类型
t
的选项。具体来说,这行代码与
getSomeOrNull
函数内部的
match(o:?>opt)不匹配。可选类型不限于字符串类型。它是泛型类型。您尝试过我的解决方案吗?它应该适用于任何选项类型。我已经初步测试过,它似乎可以工作。我会更彻底地测试,如果我遇到任何问题,会告诉你。谢谢
let getSomeOrNull (t: Type) (o: obj) =
    if isNull o then null
    else t.GetProperty("Value").GetValue(o)
let getSomeOrNull (o: obj) =
    match o with
    | :? Option<string> as o -> a |> Option.toObj > box
    | _ -> null