2010-10-27 13 views
11

मुझे पता है कि म्यूटेबल ऑब्जेक्ट्स का उपयोग करके एफ # में क्रमबद्ध करने के लिए कैसे, लेकिन क्या एक्सएमएलएसरिएलाइज़र या डेटाकंट्रैक्टसेरियलाइज़र का उपयोग करके रिकॉर्ड प्रकारों का उपयोग करके क्रमबद्ध/deserialize करने का कोई तरीका है? लग रहा है KnownType विशेषता का उपयोग कर एक साथ भेदभाव संघ के लिए यह करने के लिए एक तरह से वहाँ है, लेकिन मैं एक तरह से डिफ़ॉल्ट निर्माता के बिना गैर परिवर्तनशील रिकॉर्ड का उपयोग करने के लिए देख रहा हूँ की तरह ...F # रिकॉर्ड प्रकारों का क्रमबद्धता

+0

मैं सिर्फ एक्सएमएल पार्सिंग का उपयोग कर समाप्त हुआ, जो कि मेरे मामले में भी ठीक था, मैंने जो कुछ भी कोशिश की वह क्लीन एक्सएमएल का उत्पादन करने के लिए काम नहीं करता था, यहां तक ​​कि सिस्टम.एक्सएमएल। सिराइलाइजेशन के गुणों का उपयोग करने के लिए टॉमस के सुझावों के साथ भी, मेरा संदेह था कि यह था काम नहीं करने के लिए, लेकिन मैंने वैसे भी कोशिश करने का फैसला किया और उन्होंने नहीं किया, मुझे विश्वास है क्योंकि डेटाकंट्रैक्ट का नामस्थान इन्हें अनदेखा करता है। मेरी आवश्यकता इस अभ्यास के लिए गैर-परिवर्तनीय रिकॉर्ड का उपयोग करना था, लेकिन यदि आपका लक्ष्य सिर्फ एक्सएमएल क्रमबद्धता है, तो यह किसी भी अन्य .NET भाषा में इसका उपयोग करने से अलग नहीं है, बस कक्षाएं बनाएं, उन्हें सजाने और XmlSerializer का उपयोग करें, यह काम करेगा। – Alex

उत्तर

9

नमूना code for reading data from Freebase जोमो फिशर द्वारा करने के लिए DataContractJsonSerializer का उपयोग करता है अपरिवर्तनीय एफ # रिकॉर्ड में डेटा लोड करें। रिकॉर्ड की घोषणा वह इस तरह दिखता है का उपयोग करता है:

[<DataContract>] 
type Result<'TResult> = { // ' 
    [<field: DataMember(Name="code") >] 
    Code:string 
    [<field: DataMember(Name="result") >] 
    Result:'TResult // ' 
    [<field: DataMember(Name="message") >] 
    Message:string } 

कुंजी यहां मुद्दा यह है कि DataMember विशेषता अंतर्निहित क्षेत्र है कि वास्तव में और केवल पढ़ने के लिए संपत्ति के लिए नहीं डाटा स्टोर करने के लिए इस्तेमाल किया है से जुड़ा हुआ है है कि एफ # कंपाइलर उत्पन्न करता है (विशेषता पर field: संशोधक का उपयोग कर)।

मुझे यकीन है कि अगर यह (नहीं शायद) क्रमबद्धता के अन्य प्रकार के साथ काम करने जा रहा है 100% नहीं कर रहा हूँ, लेकिन यह साथ शुरू करने के लिए एक उपयोगी सूचक हो सकता है ...

संपादित मैं 2 आप इस तरह विशेषताओं को जोड़ने कर सकते हैं क्लीनर एक्सएमएल तो जनरेट करना चाहते हैं

module Demo 

#r "System.Runtime.Serialization.dll" 

open System.IO 
open System.Text 
open System.Xml 
open System.Runtime.Serialization 

type Test = 
    { Result : string[] 
    Title : string } 

do 
    let sb = new StringBuilder() 
    let value = { Result = [| "Hello"; "World" |]; Title = "Hacking" } 
    let xmlSerializer = DataContractSerializer(typeof<Test>); 
    xmlSerializer.WriteObject(new XmlTextWriter(new StringWriter(sb)), value) 
    let sr = sb.ToString() 
    printfn "%A" sr 

    let xmlSerializer = DataContractSerializer(typeof<Test>); 
    let reader = new XmlTextReader(new StringReader(sr)) 
    let obj = xmlSerializer.ReadObject(reader) :?> Test 
    printfn "Reading: %A" obj 

संपादित करें:

नहीं यकीन है कि मैं यहाँ कुछ याद आ रही है, तो रही है, लेकिन निम्न बुनियादी उदाहरण मेरे लिए ठीक काम करता है
[<XmlRoot("test")>] 
type Test = 
    { [<XmlArrayAttribute("results")>] 
    [<XmlArrayItem(typeof<string>, ElementName = "string")>] 
    Result : string[] 
    [<XmlArrayAttribute("title")>] 
    Title : string } 
+0

यह एक शुरुआत है, लेकिन उत्पन्न होने वाला एक्सएमएल "साफ" नहीं है, मेरा मतलब है कि टैग "FSI_0132" की तरह हैं।टेस्ट और शीर्षक_x0040_ के बजाय शीर्षक के बजाय "परीक्षण करें। मुझे लगता है कि xml टैग को [] जैसे गुणों के साथ टाइप नहीं किया जा सकता है। दूसरे शब्दों में, एक्सएमएल इंटरमीडिएट दिखता है, ऐसा कुछ नहीं जो मैं वास्तव में कर सकता था उपयोग करें। बीटीडब्ल्यू, टॉमस, मैं आपकी रीयल-वर्ल्ड फ़ंक्शनल प्रोग्रामिंग पुस्तक को पढ़ना शुरू कर रहा हूं, यह अब तक बहुत अच्छा दिखता है। – Alex

+0

नामस्थान "एफएसआई_0132" एफ # इंटरएक्टिव द्वारा संकलित कोड में उत्पन्न होता है, इसे आपके वास्तविक नेमस्पेस से बदल दिया जाएगा संपत्ति के नाम के बारे में निश्चित नहीं है, यद्यपि –

+0

@ जोएल: ठीक है, मैं समझता हूं, लेकिन मेरा लक्ष्य किसी भी नामस्थान जानकारी के बिना स्वच्छ एक्सएमएल रखना है, जैसे कि यदि आप XmlSerializer क्लास का उपयोग करके deserialize करने की कोशिश की है तो .net – Alex

1

आप XML स्वरूप को कक्षाओं के गुणों पर भी टिप्पणियां की इस श्रृंखला का उपयोग कर सकते हैं:

[XmlRoot("root")] 
[XmlElement("some-element")] 
[XmlAttribute("some-attribute")] 
[XmlArrayAttribute("collections")] 
[XmlArrayItem(typeof(SomeClass), ElementName = "item")] 

मैं अपने ग # वर्गों पर विशेषताओं का उपयोग, लेकिन एफ # में deserialize (ग # कक्षाएं इना lib संदर्भित)।

च # में

:

use file = new FileStream(filePath, FileMode.Open) 
let serializer= XmlSerializer(typeof<SomeClass>) 
let docs = serializer.Deserialize file :?> SomeClass 
+1

यह अच्छा है, लेकिन आवश्यकता गैर-परिवर्तनीय प्रकारों का उपयोग करना है, इसलिए यह दृष्टिकोण काम नहीं करेगा क्योंकि कक्षा में उत्परिवर्तनीय फ़ील्ड होंगे – Alex

9

यह XmlSerializer या DataContractSerializer का उपयोग नहीं करता है, लेकिन Json.NET 6.0 includes nice F# support.

यह इस तरह दिखता है:

type TestTarget = 
    { a: string 
     b: int } 

[<TestFixture>] 
type JsonTests() = 
    [<Test>] 
    member x.``can serialize``() = 
     let objectUnderTest = { TestTarget.a = "isa"; b = 9 } 
     let jsonResult: string = Newtonsoft.Json.JsonConvert.SerializeObject(objectUnderTest) 
     printfn "json is:\n%s" jsonResult 
     let xmlResult = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(jsonResult, "root") 
     printfn "xml is:\n%s" (xmlResult.OuterXml) 

     let jsonRoundtrip = Newtonsoft.Json.JsonConvert.DeserializeObject<TestTarget>(jsonResult) 
     printfn "json roundtrip: %A" jsonRoundtrip 

     let xmlAsJson = Newtonsoft.Json.JsonConvert.SerializeXmlNode(xmlResult, Newtonsoft.Json.Formatting.Indented, true) 
     printfn "object -> json -> xml -> json:\n%A" xmlAsJson 
     let xmlRoundtrip = Newtonsoft.Json.JsonConvert.DeserializeObject<TestTarget>(xmlAsJson) 
     printfn "xml roundtrip:\n%A" xmlRoundtrip 

     Assert.That(true, Is.False) 
     () 

json is: 
{"a":"isa","b":9} 
xml is: 
<root><a>isa</a><b>9</b></root> 
json roundtrip: {a = "isa"; 
b = 9;} 
object -> json -> xml -> json: 
"{ 
    "a": "isa", 
    "b": "9" 
}" 
xml roundtrip: 
{a = "isa"; 
b = 9;} 
+0

'[]' attr की आवश्यकता के बिना रिकॉर्ड प्रकारों का उपयोग करने के लिए एक तरीका दिखाने के लिए कमाल (बस अपना नयाटो अपग्रेड करें nsoft) – Maslow

+0

मैंने पाया कि यह सदस्य नामों की केस संवेदनशीलता का सम्मान नहीं करता है (वे हमेशा कम मामले में परिवर्तित हो जाते हैं)। –

11

एफ # 3.0 के साथ शुरू, रिकॉर्ड की क्रमबद्धता प्रकार अब CliMutableAttribute को इस प्रकार से लागू करके समर्थित है। उदाहरण:

[<CLIMutable>] 
type MyRecord = { Name : string; Age : int } 

यह उदाहरण http://blogs.msdn.com/b/fsharpteam/archive/2012/07/19/more-about-fsharp-3.0-language-features.aspx, जो इस सुविधा की चर्चा और तीन में अन्य नई सुविधाओं में शामिल हैं से लिया जाता है एफ # 3.0: ट्रिपल उद्धृत तार, स्वत: गुण, और अप्रयुक्त चर चेतावनी।