เหตุใดคุณสมบัติที่ไม่มีตัวตั้งค่าจึงไม่ถูกทำให้เป็นอนุกรม


102

ฉันมีคลาสที่ทำให้เป็นอนุกรมได้และหนึ่งในคุณสมบัติในคลาสของฉันสร้างขึ้นGuidใน getter คุณสมบัติไม่ใช้ตัวตั้งค่าและละเว้นระหว่างการทำให้เป็นอนุกรม เหตุใดจึงเป็นเช่นนั้นและฉันจึงต้องใช้ตัวตั้งค่าเสมอเพื่อให้คุณสมบัติของฉันเป็นแบบอนุกรม

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
    }
}

ฉันลองใช้ตัวตั้งค่าว่างและได้รับการจัดลำดับอย่างถูกต้อง

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
        set {}
    }
}

อัปเดต :

คุณช่วยชี้ให้เห็นได้อย่างไรว่าฉันจะกำหนดคุณสมบัติที่ค่าไม่เคยเปลี่ยนแปลงหรือค่าที่สร้างขึ้นภายในได้อย่างไร


1
ตัวอย่างที่สองทำให้เป็นอนุกรมได้อย่างถูกต้อง ... แต่จะเกิดอะไรขึ้นเมื่อคุณพยายามที่จะ deserialize?
LightStriker

ลอง YAXLib [+ , + ]
Sina Iravanian

3
FYI, [Serializable]ละเว้น
John Saunders

@JohnSaunders ฉันไม่รู้เรื่องนั้น
Konstantin Dinev

คำตอบ:


61

เป็นข้อ จำกัด ที่XmlSerializerจะไม่ทำให้คุณสมบัติแบบอ่านอย่างเดียวเป็นอนุกรมสิ่งที่คุณทำในตัวอย่างที่สองคือการแฮ็กเพื่อทำให้เป็นซีเรียลไลซ์เป็นหลักอย่างไรก็ตามจะไม่มีประโยชน์หากคุณต้องการให้ deserialize ในภายหลัง

หรือคุณสามารถเปลี่ยนไปใช้DataContractSerializerได้ซึ่งมีความยืดหยุ่นมากกว่า


8
DataContractSerializer ยังต้องการตัวตั้งค่า นี่เป็นข้อ จำกัด เพราะแม้ว่าเราอาจจะใช้มันสำหรับการดำเนินการเพียงประเภทเดียว แต่พูดว่า deserialization แต่การประกาศจำเป็นต้องมีสำหรับทั้งสองอย่างไม่เช่นนั้นกระบวนการทำให้เป็นอนุกรมจะไม่ทราบว่าจะทำอย่างไรกับค่าเมื่อพยายามทำให้เป็นอนุกรม XML ลงในวัตถุ
ryadavilli

7
@ryadavilli สิ่งที่ทำเครื่องหมายว่า[DataMember]ถูกทำให้เป็นอนุกรมโดยใช้DataContractSerializer(อ่านอย่างเดียวหรือไม่)
เจมส์

1
@ เจมส์ฉันเขียนข้างต้นเพราะฉันมีข้อผิดพลาดเกี่ยวกับเวลาในการคอมไพล์เมื่อฉันลองทำแบบเดียวกัน ตอนนี้เมื่อฉันกลับไปที่รหัสของฉันและลบตัวตั้งค่าดูเหมือนว่าจะรวบรวมได้ดี นี่เป็นเรื่องที่แปลกมากและอาจเป็นการบ้านให้ฉันค้นคว้าเพิ่มเติมเกี่ยวกับเรื่องนี้
ryadavilli

3
ในที่สุด Ahhh ก็พบที่มาของความสับสนของฉัน ไม่จำเป็นต้องใช้ตัวตั้งค่าคุณสมบัติสำหรับการทำให้เป็นอนุกรม อย่างไรก็ตามหากคุณสมบัติไม่มีตัวตั้งค่า XML จะไม่แยกค่าสถานะไปยังอ็อบเจ็กต์ ที่นั่นการบ้านเสร็จ
ryadavilli

1
@ryadavilli ใช่แล้วมันเป็นเพียงข้อ จำกัด ของการXmlSerializerใช้งานมันขึ้นอยู่กับวิธีการตั้งค่าสาธารณะ DataContractSerializerฉลาดกว่าเล็กน้อยในแง่นั้น (อาจใช้การสะท้อนเพื่อกำหนดสนามเบื้องหลัง)
เจมส์

10

ดู "การแนะนำ XML Serialization " ในเอกสาร MSDN เหนือสิ่งอื่นใดกล่าวว่า:

รายการที่สามารถต่อลำดับได้

รายการต่อไปนี้สามารถทำให้เป็นอนุกรมได้โดยใช้คลาส XmlSerializer:

Public read/write properties and fields of public classes.

Classes that implement ICollection or IEnumerable.

บันทึก:

Only collections are serialized, not public properties.
XmlElement objects.

XmlNode objects.

DataSet objects.

นอกจากนี้โปรดดูที่ " เหตุใดคลาส XML-Serializable จึงต้องมีตัวสร้างแบบไม่มีพารามิเตอร์ "


นอกจากนี้ IXmlSerializable

นอกเหนือจากประเภทข้างต้นซึ่งสามารถทำให้เป็นอนุกรมโดย XML Serializer แล้วประเภทใด ๆ ที่ใช้อินเทอร์เฟซ IXmlSerializable สามารถทำให้เป็นอนุกรมและ deserialized ได้ โดยเฉพาะอย่างยิ่งนั่นหมายความว่าประเภท XElement และ XDocument สามารถต่ออนุกรมกันได้

ดู " IXmlSerializable Interface "


6

ข้อ จำกัด ของXMLSerializer- คุณสมบัติที่ไม่มี setter ไม่สามารถต่ออนุกรมได้

แต่คุณสามารถใช้DataContractSerializerเพื่อทำให้เป็นอนุกรมprivate setter properties-

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}

1
คุณสมบัตินี้ควรถูกทำให้เป็นอนุกรมเป็นแอตทริบิวต์ xml (ดูโพสต์ต้นฉบับ) รหัสของคุณ (แอตทริบิวต์ DataMember) สร้างองค์ประกอบ xml เท่าที่ฉันรู้ไม่มีวิธี (สะอาด) ในการบอก DataContractSerializer ให้เปลี่ยนคุณสมบัติเป็นแอตทริบิวต์ไม่ใช่องค์ประกอบ DataContractSerializer เป็นสิ่งที่ดี แต่คุณต้องคำนึงถึงข้อ จำกัด นี้เสมอ
sth_Weird

2

หากคุณต้องการมีตัวตั้งค่าส่วนตัวและให้อ็อบเจ็กต์สามารถทำให้เป็นอนุกรม / deserialhable, อนุมานได้ว่า ISerializable และสร้างตัวสร้างเช่น MyObject (ข้อมูล SerializationInfo, บริบท StreamingContext) ตัวอย่างพบได้ที่นี่


0

แอตทริบิวต์การทำให้เป็นอนุกรมใช้เพื่อทำให้เป็นอนุกรมและแยกวัตถุ XmlSerializer จะถือว่าคุณไม่จำเป็นต้องทำให้เป็นอนุกรมคุณสมบัติใด ๆ ที่ไม่มีตัวตั้งค่า Setter จะถูกใช้เมื่อต้องการแยกสตริงออกเป็นอ็อบเจ็กต์เนื่องจากต้องสร้างอินสแตนซ์ของอ็อบเจ็กต์จากนั้นตัวเซ็ตเตอร์จะถูกใช้เพื่อเติมค่าคุณสมบัติ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.