[英]F# Add Constructor to a Record?
基本上,我希望有一個結構來處理序列化為JSON和格式化的xml。 記錄可以很好地用於從json序列化到/從json序列化。 但是,XmlSerializer需要無參數的構造函數。 我真的不希望通過練習為這些構造構建類對象(僅適用於原理)。 我希望可以有一些捷徑將無參數的構造函數添加到記錄中(也許帶有無線語句等)。 我無法表現出來-社區中有人有運氣嗎?
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)
我希望Blockquote能夠為將無參數構造函數添加到記錄中提供一些捷徑
在F#3.0版中,可以通過使用CLIMutable屬性來實現。 將其添加到無參數構造函數和讀/寫屬性(而不是只讀屬性)的記錄類型中。
為什么不使用DataContractSerializer(用於Xml)而不是XmlSerializer? 這是數據合同(針對多個投影的相同編程模型)的主要好處之一。
(無法為F#記錄創建無參數構造函數。)
看起來您無法將記錄更改為類-或向其中添加edfault構造函數。
提供的示例(基於本文: http : //blogs.msdn.com/b/jomo_fisher/archive/2010/03/06/neat-sample-f-and-freebase.aspx )從api獲取json流.freebase.com; 然后我們反序列化為歸因的類; 接下來將其序列化為Json到磁盤; 然后將其序列化為Xml到磁盤(使用DataContract); 最后,最好地控制輸出,將其序列化為Xml到磁盤(使用XmlSerializer):
筆記:
DataContractJsonSerializer和JSON.DataContractJsonSerializer的DataContract(family of)屬性-這些發生在類名稱和成員變量上。 DataContract的內容非常簡單-並適用於記錄類型。
XmlSerializer(family of)類和屬性Getter / Setter的屬性。 這就要求該類型是一個具有默認構造函數的對象,以及具有與它們各自關聯的屬性的屬性Getters和Setters。 如果Property沒有egethr或setter,它將不會序列化-這是一個意外(我想默認的構造函數將確保對象在反序列化時具有defulat值,並且setter將使用序列化的內容進行更新-但沒有並非如此)。
約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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.