当编译器坚持认为不可能时,如何从Newtonsoft检查“ null”?

kor*_*dge 3 .net null f# json.net optional

我们的项目将C#和F#与ASP.NET Core混合在一起。ASP.NET内核默认使用Newtonsoft来在任何地方进行序列化/反序列化,而且庞大的文档生成(nswag)也依赖于类似于CLI(Mutable)的DTO来生成正确的类型。

我们的DTO在F#中定义如下:

[<CLIMutable>]
type Query =
    { Status: string
      Offset: int
      Limit: int }
Run Code Online (Sandbox Code Playgroud)

这使得Newtonsoft进行序列化和nswag生成swagger doc变得很简单。

但..!我在使用null / option“ mismatch”时非常困难。C#/ Newtonsoft / NSwag坚持使用null,并且不会理解F#option。所以在我的F#中,我必须检查null并将它们转换为option;从域转换回DTO时,还将我的选项转换回null。

但是F#坚持认为,在什至不允许我检查的情况下,不可能出现null:编译器给我:“类型{...}没有适当的'null'”。但事实是,运行时,它IS空,因为这是Newtonsoft是如何工作的。Newtonsoft是 .NET标准看来,所以我不认为用别的东西是可行的不幸。

即使F#认为不可能为null,我如何检查null?

Aar*_*ach 6

解决这个问题的简单方法(通常)是在检查空值之前将值装箱。

let isReallyNull value = value |> box |> isNull

然后,您可以按照常规逻辑检查Newtonsoft返回的对象实例:

if dto |> isReallyNull
then None
else Some dto
Run Code Online (Sandbox Code Playgroud)

这是一个完整的示例Unchecked.defaultof,用于为编译器说不能为null的类型生成null值:

[<CLIMutable>]
type MyDto =
    {
        Status: string
        Offset: int
        Limit: int
    }

let isReallyNull value = value |> box |> isNull

let dto = Unchecked.defaultof<MyDto>

// if dto |> isNull (* Compiler complains that MyDto does not have null as a proper value *)
if dto |> isReallyNull
then printfn "The DTO is null"
else printfn "The DTO is non-null"
Run Code Online (Sandbox Code Playgroud)