代码之家  ›  专栏  ›  技术社区  ›  akaphenom

F#向记录添加构造函数?

  •  2
  • akaphenom  · 技术社区  · 16 年前

    基本上,我希望有一个单一的构造来处理序列化为JSON和格式化的xml。记录可以很好地序列化到json或从json序列化。但是,XmlSerializer需要无参数构造函数。我真的不想经历为这些构造构建类对象的练习(仅适用于原则)。我希望能有一些捷径把一个无参数的构造函数放到一个记录上(也许是用wioth语句之类的)。我不能让它规矩点-社区里有人运气好吗?

    module JSONExample
        open System
        open System.IO 
        open System.Net 
        open System.Text 
        open System.Web 
        open System.Xml
        open System.Security.Authentication 
        open System.Runtime.Serialization //add assemnbly reference System.Runtime.Serialization System.Xml
        open System.Xml.Serialization
        open System.Collections.Generic 
    
        [<DataContract>]            
        type ChemicalElementRecord = { 
            [<XmlAttribute("name")>]
            [<field: DataMember(Name="name") >] 
            Name:string 
    
            [<XmlAttribute("name")>]
            [<field: DataMember(Name="boiling_point") >] 
            BoilingPoint:string 
    
            [<XmlAttribute("atomic-mass")>]
            [<field: DataMember(Name="atomic_mass") >] 
            AtomicMass:string 
        } 
    
        [<XmlRoot("freebase")>]
        [<DataContract>] 
        type FreebaseResultRecord = { 
            [<XmlAttribute("code")>]
            [<field: DataMember(Name="code") >] 
            Code:string 
    
            [<XmlArrayAttribute("results")>]
            [<XmlArrayItem(typeof<ChemicalElementRecord>, ElementName = "chemical-element")>]
            [<field: DataMember(Name="result") >] 
            Result: ChemicalElementRecord array
    
            [<XmlElement("message")>] 
            [<field: DataMember(Name="message") >] 
            Message:string 
            } 
    
    
        let getJsonFromWeb() = 
            let query = "[{'type':'/chemistry/chemical_element','name':null,'boiling_point':null,'atomic_mass':null}]"
            let query = query.Replace("'","\"") 
            let queryUrl = sprintf "http://api.freebase.com/api/service/mqlread?query=%s" "{\"query\":"+query+"}" 
    
            let request : HttpWebRequest = downcast WebRequest.Create(queryUrl) 
            request.Method <- "GET" 
            request.ContentType <- "application/x-www-form-urlencoded" 
    
            let response = request.GetResponse() 
    
            let result = 
                try 
                    use reader = new StreamReader(response.GetResponseStream()) 
                    reader.ReadToEnd(); 
                finally 
                    response.Close() 
    
            let data = Encoding.Unicode.GetBytes(result); 
            let stream = new MemoryStream() 
            stream.Write(data, 0, data.Length); 
            stream.Position <- 0L 
            stream
    
    
    
        let test =
            // get some JSON from the web
            let stream = getJsonFromWeb()
    
            // convert the stream of JSON into an F# Record
            let JsonSerializer = Json.DataContractJsonSerializer(typeof<FreebaseResultRecord>) 
            let result: FreebaseResultRecord = downcast JsonSerializer.ReadObject(stream) 
    
            // save the Records to disk as JSON 
            use fs = new FileStream(@"C:\temp\freebase.json", FileMode.Create) 
            JsonSerializer.WriteObject(fs,result)
            fs.Close()
    
            // save the Records to disk as System Controlled XML
            let xmlSerializer = DataContractSerializer(typeof<FreebaseResultRecord>);
            use fs = new FileStream(@"C:\temp\freebase.xml", FileMode.Create) 
            xmlSerializer.WriteObject(fs,result)
            fs.Close()
    
            use fs = new FileStream(@"C:\temp\freebase-pretty.xml", FileMode.Create) 
            let xmlSerializer = XmlSerializer(typeof<FreebaseResultRecord>)
            xmlSerializer.Serialize(fs,result)
            fs.Close()
    
    ignore(test)
    
    3 回复  |  直到 16 年前
        1
  •  5
  •   bentayloruk    13 年前

    Blockquote我希望有一些捷径可以让一个无参数的构造函数进入一个记录

    在F#版本3.0中,通过使用 CLIMutable 属性。将其添加到无参数构造函数和读/写属性(而不是只读属性)的记录类型中。

        2
  •  1
  •   Brian    16 年前

    为什么不使用DataContractSerializer(对于Xml)而不是XmlSerializer?这是数据契约的主要好处之一(对于多个预测,使用相同的编程模型)。

        3
  •  1
  •   akaphenom    16 年前

    看起来您不能将记录更改为类,也不能向其中添加edfault构造函数。

    http://blogs.msdn.com/b/jomo_fisher/archive/2010/03/06/neat-sample-f-and-freebase.aspx

    笔记:

    的DataContract(系列)属性 DataContractJsonSerializer和 JSON.DataContractJsonSerializer- memeber变量。数据合同 事情是直截了当的-而且 也适用于记录类型。

    在阶级和财产上 盖特/塞特。这需要类型 是具有默认值的对象 设置器w/与 有一个能手还是一个能手 施工人员将确保 对象上有不确定的值 用序列化的内容更新- 但事实并非如此)。

    俏皮 (叹息)关于 XmlSerialization是指 我们把类型移到一个名称空间。。。

    namespace JSONExample
        open System
        open System.IO 
        open System.Net 
        open System.Text 
        open System.Web 
        open System.Xml
        open System.Security.Authentication 
        open System.Runtime.Serialization //add assemnbly reference System.Runtime.Serialization System.Xml
        open System.Xml.Serialization
        open System.Collections.Generic 
    
        [<DataContract>]            
        type ChemicalElementRecord() =  
            [<field: DataMember(Name="name") >] 
            let mutable name: string  = ""
    
            [<field: DataMember(Name="boiling_point") >] 
            let mutable boilingPoint: string =""
    
            [<field: DataMember(Name="atomic_mass") >] 
            let mutable atomicMass: string  = ""
    
            [<XmlAttribute("name")>]
            member this.Name with get() = name and set v = name <- v
    
            [<XmlAttribute("boiling-point")>]
            member this.BoilingPoint with get()  = boilingPoint  and set v = boilingPoint <- v
    
            [<XmlAttribute("atomic-mass")>]
            member this.AtomicMass with get() = atomicMass  and set v = atomicMass <- v
    
        [<XmlRoot("freebase")>]
        [<DataContract>] 
        type FreebaseResultRecord() =  
    
            [<field: DataMember(Name="code") >] 
            let mutable code: string = ""
    
            [<field: DataMember(Name="result") >] 
            let mutable result: ChemicalElementRecord array = Array.empty
    
            [<field: DataMember(Name="message") >] 
            let mutable message: string = ""
    
            [<XmlElement("message")>] 
            member this.Message with get() : string = message and set v = message <- v
    
            [<XmlArrayAttribute("chemical-elements")>]
            [<XmlArrayItem(typeof<ChemicalElementRecord>, ElementName = "chemical-element")>]
            member this.Result with get() = result and set v = result <- v
    
            [<XmlAttribute("code")>]
            member this.Code with get() = code and set v = code <- v
    
        module Test = 
            let getJsonFromWeb() = 
                let query = "[{'type':'/chemistry/chemical_element','name':null,'boiling_point':null,'atomic_mass':null}]"
                let query = query.Replace("'","\"") 
                let queryUrl = sprintf "http://api.freebase.com/api/service/mqlread?query=%s" "{\"query\":"+query+"}" 
    
                let request : HttpWebRequest = downcast WebRequest.Create(queryUrl) 
                request.Method <- "GET" 
                request.ContentType <- "application/x-www-form-urlencoded" 
    
                let response = request.GetResponse() 
    
                let result = 
                    try 
                        use reader = new StreamReader(response.GetResponseStream()) 
                        reader.ReadToEnd(); 
                    finally 
                        response.Close() 
    
                let data = Encoding.Unicode.GetBytes(result); 
                let stream = new MemoryStream() 
                stream.Write(data, 0, data.Length); 
                stream.Position <- 0L 
                stream
    
    
    
            let test =
                // get some JSON from the web
                let stream = getJsonFromWeb()
    
                // convert the stream of JSON into an F# Record
                let JsonSerializer = Json.DataContractJsonSerializer(typeof<FreebaseResultRecord>) 
                let result: FreebaseResultRecord = downcast JsonSerializer.ReadObject(stream) 
    
                // save the Records to disk as JSON 
                use fs = new FileStream(@"C:\temp\freebase.json", FileMode.Create) 
                JsonSerializer.WriteObject(fs,result)
                fs.Close()
    
                // save the Records to disk as System Controlled XML
                let xmlSerializer = DataContractSerializer(typeof<FreebaseResultRecord>);
                use fs = new FileStream(@"C:\temp\freebase.xml", FileMode.Create) 
                xmlSerializer.WriteObject(fs,result)
                fs.Close()
    
                use fs = new FileStream(@"C:\temp\freebase-pretty.xml", FileMode.Create) 
                let xmlSerializer = XmlSerializer(typeof<FreebaseResultRecord>)
                xmlSerializer.Serialize(fs,result)
                fs.Close()
    
    
            ignore(test)