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