扩展第三方库中的类型以进行序列化 [英] Extending types in third-party library for serialization

查看:36
本文介绍了扩展第三方库中的类型以进行序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个将类型从第三方库转换为 IDictionary 的函数,以便可以轻松地将它们序列化(转换为JSON).类型之间存在依赖关系,因此有时会嵌套字典.

I need a function to convert types from a third-party library to IDictionarys so they can be easily serialized (to JSON). There are dependencies between the types so the dictionaries are sometimes nested.

现在我有类似这样的东西:

Right now I have something hideous like this:

//Example type
type A(name) = 
  member __.Name  = name

//Example type
type B(name, alist) =
  member __.Name = name
  member __.AList : A list = alist

let rec ToSerializable x =
  match box x with
  | :? A as a -> dict ["Name", box a.Name]
  | :? B as b -> dict ["Name", box b.Name; "AList", box (List.map ToSerializable b.AList)]
  | _ -> failwith "wrong type"

这会将所有内容转换为原始类型,此类的 IEnumerable 或字典.

This would convert everything to a primitive type, an IEnumerable of such a type, or a dictionary.

此功能将随着类型的添加(ugh)而不断增长.它不是类型安全的(要求使用包罗万象的模式).找出支持哪种类型需要仔细研究整体模式匹配.

This function will keep growing as types are added (ugh). It's not type-safe (requiring the catch-all pattern). Figuring out which types are supported requires perusing the monolithic pattern match.

我希望能够做到这一点:

I'd love to be able to do this:

type ThirdPartyType with
  member x.ToSerializable() = ...

let inline toSerializable x =
  (^T : (member ToSerializable : unit -> IDictionary<string,obj>) x)

let x = ThirdPartyType() |> toSerializable //type extensions don't satisfy static member constraints

所以,我在这里寻找创造力.有什么更好的方法可以解决我的投诉?

So, I'm looking for creativity here. Is there a better way to write this that addresses my complaints?

推荐答案

以下是解决类型安全性问题的一种可能的解决方案,尽管不一定是您的可扩展性问题:

Here's one possible solution that addresses the type-safety question, though not necessarily your extensibility question:

// these types can appear in any assemblies
type A = { Name : string }
type B = { Name : string; AList : A list }
type C(name:string) =
    member x.Name = name
    static member Serialize(c:C) = dict ["Name", box c.Name]

 

// all of the following code goes in one place
open System.Collections.Generic

type SerializationFunctions = class end

let inline serializationHelper< ^s, ^t when (^s or ^t) : (static member Serialize : ^t -> IDictionary<string,obj>)> t = 
    ((^s or ^t) : (static member Serialize : ^t -> IDictionary<string,obj>) t)
let inline serialize t = serializationHelper<SerializationFunctions,_> t

// overloads for each type that doesn't define its own Serialize method
type SerializationFunctions with
    static member Serialize (a:A) = dict ["Name", box a.Name]
    static member Serialize (b:B) = dict ["Name", box b.Name; "AList", box (List.map serialize b.AList)]

let d1 = serialize { A.Name = "a" }
let d2 = serialize { B.Name = "b"; AList = [{ A.Name = "a" }]}
let d3 = serialize (C "test")

这篇关于扩展第三方库中的类型以进行序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆