การทำให้เป็นอนุกรม WCF DataContract ของคุณสมบัติอ่านอย่างเดียว?

เมื่อใดก็ตามที่ฉันใช้ WCF ฉันมักจะพยายามสร้างคลาสที่ไม่เปลี่ยนรูปแบบซึ่งจบลงด้วยการข้ามสาย (เช่น พารามิเตอร์ที่ตั้งค่าในตัวสร้าง คุณสมบัติเป็นแบบอ่านอย่างเดียว) อย่างไรก็ตาม สิ่งนี้ขัดขวางการทำซีเรียลไลซ์ WCF ซึ่งต้องการให้คุณสมบัติทั้งหมดเป็น Public get/set (ซึ่งก็สมเหตุสมผล เพราะจะต้องทำการดีซีเรียลไลซ์คุณสมบัติเหล่านั้น)

แม้แต่ในโพสต์ที่เกี่ยวข้องนี้ ฉันเห็นว่าวิธีแก้ปัญหาของพวกเขาจบลงด้วยการ ทุกสิ่งที่สาธารณะซึ่งละเมิดความรู้สึกในการเขียนโปรแกรมที่ดีของฉัน มีวิธีแก้ไขปัญหานี้ไหม? ฉันจำเป็นต้องยอมรับวิธีแก้ปัญหานี้หรือบางอย่างเช่นความไม่เปลี่ยนรูปของไอศกรีมแท่งแล้วพอใจกับมันหรือไม่?

อีกสิ่งหนึ่งที่ฉันลองคือสิ่งนี้ โดยที่ฉันจะมีคลาสพื้นฐานสำหรับทุกสิ่งและคลาสที่ได้รับซึ่งทำให้เซ็ตนี้ไร้ประโยชน์:

/// <summary>
/// This represents a discovered virtual-machine template that can be
/// instantiated into a RunningVirtualMachine
/// </summary>
[DataContract]
[XmlRoot("VMTemplate")]
public class VirtualMachineTemplateBase
{
    [DataMember]
    public virtual ulong SizeInBytes { get; set; }
}

/// <summary>
/// This class is the real guts of VirtualMachineTemplate that we're hiding
/// from the base class.
/// </summary>
[XmlInclude(typeof(VirtualMachineTemplateBase))]
public class VirtualMachineTemplate : VirtualMachineTemplateBase, IXmlPicklable, IEnableLogger
{
    ulong _SizeInBytes;
    public override ulong SizeInBytes {
        get { return _SizeInBytes; }
        set { }
    }
}

person Ana Betts    schedule 27.08.2009    source แหล่งที่มา


คำตอบ (2)


หากคุณใช้ DataContractSerializer (ซึ่งเป็นค่าเริ่มต้นสำหรับ WCF) คุณสามารถทำให้ซีเรียลไลซ์ใดๆ ที่ตกแต่งด้วยแอตทริบิวต์ [DataMember] ได้ แม้แต่ฟิลด์แบบอ่านอย่างเดียว:

[DataContract]
public class VirtualMachineTemplate : VirtualMachineTemplateBase, IXmlPicklable, IEnableLogger
{
    [DataMember]
    ulong _SizeInBytes;
}

แต่คุณจำเป็นต้องใช้ DataContractSerializer - ไม่ใช่ XML serializer ตัวสร้างอนุกรม XML สามารถทำให้คุณสมบัติสาธารณะเป็นอนุกรมเท่านั้น (และจะทำ เว้นแต่คุณจะใส่ [XmlIgnore] ไว้)

DataContractSerializer แตกต่างออกไป:

  • ไม่จำเป็นต้องมีตัวสร้างเริ่มต้นที่ไม่มีพารามิเตอร์
  • มันจะ เฉพาะ ทำให้เป็นอนุกรมสิ่งที่คุณทำเครื่องหมายอย่างชัดเจนด้วย [DataMember]
  • แต่นั่นสามารถเป็นอะไรก็ได้ - สนาม ทรัพย์สิน และการมองเห็นใดๆ (ส่วนตัว ได้รับการคุ้มครอง สาธารณะ)
  • มันเร็วกว่า XmlSerializer เล็กน้อย แต่คุณไม่สามารถควบคุมรูปร่างของ XML ได้มากนัก - คุณจะได้ยินเฉพาะสิ่งที่รวมอยู่ด้วย

ดูบล็อกโพสต์ และบล็อกโพสต์เพื่อดูเคล็ดลับและคำแนะนำเพิ่มเติม

มาร์ก

person marc_s    schedule 27.08.2009
comment
ไม่ คุณยังต้องรวมชุดนี้ไว้ ไม่เช่นนั้นจะล้มเหลว - person Craig; 28.01.2010
comment
คุณสามารถตั้งค่า SerializeReadOnlyTypes เป็นจริงได้ใน DataContractSerializerSettings - person Mike Wasson; 01.08.2013
comment
แย่จัง ลิงก์โพสต์บล็อกเสียแล้ว :( - person pete the pagan-gerbil; 07.07.2014
comment
@petethepagan-gerbil: Archive.org เพื่อช่วยเหลือ... บล็อกโพสต์ #1 และ โพสต์บล็อก #2 - person InteXX; 10.10.2014
comment
ขอบคุณ @InteXX - แก้ไขคำตอบเพื่อรวมสิ่งเหล่านั้น;) - person pete the pagan-gerbil; 22.11.2014

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

person Erno    schedule 22.11.2013