Reflection 如何检查';不允许为null的类型的T?

Reflection 如何检查';不允许为null的类型的T?,reflection,f#,null,nullable,Reflection,F#,Null,Nullable,给定 让内联反序列化(x) |>一些 使用ex-> System.Diagnostics.Trace.WriteLine(sprintf“错误反序列化失败:%s”示例消息) 没有一个 例如,正在将obj列表返回为nullFSharpList不允许为空。在不知道't是什么的情况下,我怎么能问F#我要返回的类型是否支持null,以便我可以相应地停止/抛出/执行操作?是否有反射标志或Microsoft.FSharp.reflection…方法用于此操作?我能想到的最好方法是将结果框起来(在反序列化结

给定

让内联反序列化(x)
|>一些
使用ex->
System.Diagnostics.Trace.WriteLine(sprintf“错误反序列化失败:%s”示例消息)
没有一个

例如,正在将
obj列表
返回为
null
<代码>FSharpList不允许为空。在不知道
't
是什么的情况下,我怎么能问F#我要返回的类型是否支持
null
,以便我可以相应地停止/抛出/执行操作?是否有反射标志或Microsoft.FSharp.reflection…方法用于此操作?

我能想到的最好方法是将结果框起来(在反序列化结构的情况下)并将其与null模式匹配:

let inline deserialize<'t> x :'t option = 
    printfn "Attempting to deserialize %A" typeof<'t>.Name
    try
        JsonConvert.DeserializeObject<'t>(x)
        |> Some
    with ex ->
        System.Diagnostics.Trace.WriteLine(sprintf "Error deserialization failed:%s" ex.Message)
        None
让内联反序列化(x)
匹配框obj与
|空->无
|_uj->一些对象
使用ex->
System.Diagnostics.Trace.WriteLine(sprintf“错误反序列化失败:%s”示例消息)
没有一个
让r1=反序列化(“[1,2,3]”//val r1:obj list option=Some[1L;2L;3L]
让r2=反序列化(“null”)//val r2:obj list option=None

完整答案包括检查类型是否为记录(在这种情况下,永远不允许使用
null
),或者是否为联合(在这种情况下,如果类型具有
编译表示形式
自定义属性
,其标志包含
UseNullAsTrueValue
成员,则允许使用null)(有关详细信息)

要回答第一个问题,您可以在
FSharpType
模块()中使用
IsRecord
函数;要回答第二个问题,您可以在同一模块上使用
IsUnion
函数和
CustomAttribute
函数的组合


如果类型是设置了
UseNullAsTrueValue
的并集,您应该可以继续,只发送值。

这只是检查null,它不检查
't
是否允许为null。不确定为什么需要检查类型而不是结果值。但我想简单的反射应该做到这一点:
让typeCanBeNull=(而不是typeof)null)因为如果在F#land中允许值为null,那么如果值为null就可以了,如果不是,那么我会检查值是否为null,并决定抛出/None/我选择的任何行为作为本例的行为。这不会跳过F#创建/定义的不应该为null的类吗?我不确定是否理解。一旦创建了一个类,它就可以为null。只有F#记录/联合获得了非null的默认期望值。如果您尝试设置
let x:TestFClass=null
,则在F#中定义的类(不带
AllowNullLiteral
属性)将不会编译,因此依赖于该类型的所有F#程序集都期望它不为null。所以在F#中定义的类不应该为null,这是一个很好的观点。我在sharplab中创建了一个类,发现编译器确实添加了一个属性来表示一个F#class:`[]`因此您可以在不存在AllowNullLiteral属性的情况下查找该属性的存在,以作为该类型不允许null的信号。下面是指向比较的sharplab链接:太棒了,你能更新你的答案以包括所有部分吗?
  let inline deserialize<'t> x :'t option = 
      printfn "Attempting to deserialize %A" typeof<'t>.Name
      try
          let obj = Newtonsoft.Json.JsonConvert.DeserializeObject<'t>(x)
          match box obj with
          | null -> None
          | _ -> Some obj
      with ex ->
          System.Diagnostics.Trace.WriteLine(sprintf "Error deserialization failed:%s" ex.Message)
          None

  let r1 = deserialize<obj list> ("[1,2,3]") //val r1 : obj list option = Some [1L; 2L; 3L]
  let r2 = deserialize<obj list> ("null") //val r2 : obj list option = None