F#是否了解其受歧视的工会的编制表格?

时间:2013-07-24 11:07:35

标签: f# servicestack servicestack-text

F#中的歧视联合被编译为抽象类,其选项成为嵌套的具体类。

type DU = A | B

DU是抽象的,而DU.A和DU.B是具体的。

使用ServiceStack,可以使用函数自定义类型到JSON字符串和后面的序列化。关于DU类型,我在C#中可以做到这一点。

using ServiceStack.Text;

JsConfig<DU.A>.SerializeFn = v => "A"; // Func<DU.A, String>
JsConfig<DU.B>.SerializeFn = v => "B"; // Func<DU.B, String>
JsConfig<DU>.DeserializeFn = s =>
    if s == "A" then DU.NewA() else DU.NewB(); // Func<String, DU>

F#是否了解其歧视工会的编制表格?如何在编译时获得F#中的DU.A类型?

typeof<DU> // compiles
typeof<DU.A> // error FS0039: The type 'A' is not defined
typeof<A> // error FS0039: The type 'A' is not defined

我可以很容易地在F#中注册一个用于反序列化的函数。

open System
open ServiceStack.Text

JsConfig<DU>.RawDeserializeFn <-
    Func<_, _>(fun s -> printfn "Hooked"; if s = "A" then A else B)

对于具体类型DU.A和DU.B,是否可以在F#中完全注册序列化函数?

3 个答案:

答案 0 :(得分:8)

虽然所有行为(抽象类等)不仅仅是一个实现细节,它实际上是由规范定义的,这些东西不能从F#访问 - 这是来自规范的引用

  

编译的联合类型U具有:

     

·每个空联合案例的一个CLI静态getter属性U.C.   C.此属性获取表示每个此类的单个对象   情况下。

     

·每个非空联合案例C的一个CLI嵌套类型U.C   type具有实例属性Item1,Item2 ....用于每个字段   union case,或单个实例属性Item(如果只有一个)   领域。但是,只有一个案例的编译联合类型却没有   有一个嵌套类型。相反,联合类型本身扮演着角色   案件类型。

     

·每个非空联合案例C的一个CLI静态方法U.NewC   此方法为该案例构造一个对象。

     

·每个案例C的一个CLI实例属性U.IsC   property返回true或false。

     

·每个案例C的一个CLI实例属性U.Tag   property获取或计算与case相对应的整数标记。

     

·如果U有多个案例,则它有一个CLI嵌套类型   U.Tags。对于每种情况,U.Tags都会输入一个整数字面值   从零开始增加订单。

     

·编译的联合类型具有所需的方法   除了any之外,还实现了自动生成的接口   用户定义的属性或方法。

     

这些方法和属性可能无法直接在F#中使用。   但是,这些类型具有面向用户的List.Empty,List.Cons,   Option.None和Option.Some属性和/或方法。

重要的是,“这些方法和属性可能无法在F#中使用。”

答案 1 :(得分:5)

F#中的DU是单一类型的事实是其有用性的关键。 F#方法是使用模式匹配:

JsConfig<DU>.SerializeFn <- function
  | A -> "A"
  | B -> "B"

这个应该有效,因为联合案例不仅是C#中的嵌套类型,还有子类型。当然,如果ServiceStack不考虑基类型序列化器,那么这将不起作用。

答案 2 :(得分:4)

Daniel是正确的,您可以通过为基本类型DU注册序列化函数来完成此操作。这是一个更全面的例子

open System
open ServiceStack.Text

type DU = A | B

let serialize = function
    | A -> "A"
    | B -> "B"

let deserialize = function
    | "A" -> A
    | "B" -> B
    | _   -> failwith "Can't deserialize"

JsConfig<DU>.SerializeFn <- Func<_,_>(serialize)
JsConfig<DU>.DeSerializeFn <- Func<_,_>(deserialize)

let value = [| A; B |]
let text = JsonSerializer.SerializeToString(value)
let newValue = JsonSerializer.DeserializeFromString<DU[]>(text)

结果:

val value : DU [] = [|A; B|]
val text : string = "["A","B"]"
val newValue : DU [] = [|A; B|]