Как я могу проверить 'T для типов, которые не могут быть нулевыми? - PullRequest
2 голосов
/ 14 июня 2019

1001 * данный *

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

возвращает, например, obj list как null. FSharpList<_> не может быть нулевым. Как я могу, не зная, что 't спросить F #, поддерживает ли тип, который я собираюсь вернуть, null, чтобы я мог соответственно остановить / выбросить / действовать? Для этого есть флаг отражения или Microsoft.FSharp.Reflection... метод?

Ответы [ 2 ]

2 голосов
/ 15 июня 2019

Полный ответ включает в себя проверку, является ли тип записью (в этом случае null никогда не разрешается), или если это объединение (в этом случае допускается нулевое значение, если тип имеет CompilationRepresentation CustomAttribute, чейфлаги содержат член UseNullAsTrueValue (https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/core.compilationrepresentationflags-enumeration-%5Bfsharp%5D для более подробной информации).

Чтобы ответить на первый вопрос, вы можете использовать функцию IsRecord в модуле FSharpType (https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/reflection.fsharptype-class-%5Bfsharp%5D), а для ответа на второй вы можете использовать комбинацию функции IsUnion для этоготот же модуль и CustomAttribute охота.

В случае, если тип является объединением с установленным UseNullAsTrueValue, вам нужно идти вперед, просто отправьте значение вместе.

1 голос
/ 14 июня 2019

Лучшее, что я могу придумать, - это упаковать результат (если вы десериализуете структуры) и сопоставить шаблон с нулем:

  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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...