WCF เน้นคุณสมบัติโดยไม่มี "set" วิธีแก้ปัญหาใด ๆ


98

ฉันมีคลาสบางคลาสที่ฉันผ่านเนื่องจากเมธอดบริการและคลาสนั้นมีคุณสมบัติรับอย่างเดียว:

[DataContract]
public class ErrorBase
{
  [DataMember]
  public virtual string Message { get { return ""; } }
}

ฉันได้รับข้อยกเว้นในด้านการบริการ:

System.Runtime.Serialization.InvalidDataContractException: ไม่ได้ตั้งค่าวิธีการสำหรับคุณสมบัติ 'ข้อความ' ในประเภท 'MyNamespace.ErrorBase'

ฉันต้องมีคุณสมบัตินี้เป็นเพียงผู้เริ่มต้นฉันไม่สามารถอนุญาตให้ผู้ใช้กำหนดค่าได้ วิธีแก้ปัญหาใด ๆ ที่ฉันสามารถใช้ได้? หรือฉันไม่มีคุณสมบัติเพิ่มเติมบางอย่าง?

คำตอบ:


109

ให้ข้อความเป็นตัวตั้งค่าสาธารณะ แต่ได้รับการป้องกันเพื่อให้เฉพาะคลาสย่อย (และ DataContractSerializer เนื่องจากมันโกง :) อาจแก้ไขค่าได้


นั่นคือวิธีแก้ปัญหาที่เรียบร้อย!
Russell

ขอบคุณดีใจที่มีประโยชน์! นี่เป็นเพียงหนึ่งในหลาย ๆ วิธีสำหรับเคล็ดลับนี้ เนื่องจาก getters และ setters เป็นฟังก์ชันทางเทคนิคคุณจึงสามารถใช้เทคนิคเดียวกันนี้ในการจัดทำ serialization แบบดั้งเดิม (อาจเป็นรูปแบบเวลาที่กำหนดเองใน XML) โดยไม่จำเป็นต้องใช้ IDataContractSurrogate ที่ข่มขู่
rh.

29
คุณสามารถทำให้เป็นส่วนตัวได้ Serializer ไม่สนใจว่าจะเป็นแบบส่วนตัวสาธารณะป้องกันภายในหรือภายในที่มีการป้องกัน
Abel

8
และทำการเซ็ตเตอร์throw new NotSupportedException()
Simon_Weaver

2
มีprivate set;ผลงานถ้าคุณใช้[DataContract]และ[DataMember]. public set;ถ้าคุณไม่ใช้พวกเขาที่คุณต้องการ
user276648

12

แม้ว่าคุณจะไม่จำเป็นต้องอัปเดตค่า แต่ WCFSerializer จะใช้ setter เพื่อยกเลิกการกำหนดค่าเริ่มต้นของออบเจ็กต์ (และตั้งค่าใหม่)

ดังนั้นสิ่งนี้คือสิ่งที่คุณต้องการ: WCF DataContracts


1
ดังนั้นวิธีเดียวที่ฉันจะเอาชนะปัญหาได้คือทำให้เป็นวิธีการแทนทรัพย์สิน? อีกครั้งฉันไม่สามารถอนุญาต "set" ในพร็อพเพอร์ตี้นี้ได้
Andrey

คุณสามารถกำหนดให้เป็นวิธีการ (เช่น GetMessage () {return "";}) หรือฉันค่อนข้างแน่ใจว่าคุณสามารถบอกให้ WCF Serializer เพิกเฉยได้ ฉันจะดูสิ่งที่ฉันหาได้และแจ้งให้คุณทราบ,
รัสเซล

1
คำถาม stackoverflow นี้กระทบเล็บบนหัว: stackoverflow.com/questions/172681/wcf-datacontracts
Russell


5

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


3
มันไม่สมเหตุสมผลเลยที่จะทำให้เป็นอนุกรมของคุณสมบัติที่ได้รับ (เช่นคุณสมบัติ URL ที่คำนวณจากคุณสมบัติ ID) ไปยังหน่วยเก็บข้อมูลถาวร (เช่นฐานข้อมูล) - เพิ่มคะแนนสำหรับสิ่งนั้น - แต่มันก็สมเหตุสมผลที่จะทำให้อนุกรมเป็น การเป็นตัวแทน (เช่น JSON หรือ XML) ที่ส่งคืนโดยคำขอ API
Florian Winter

4

คุณมีตัวตั้งค่า "ไม่ต้องทำอะไร" ไม่ได้เหรอ ??

[DataContract]
public class ErrorBase
{
  [DataMember]
  public virtual string Message 
  {
      get { return ""; } 
      set { }
  }
}

หรือไม่ DataContract serializer barf ด้วย ??


14
ไม่ได้หมายความว่าฉันไม่ต้องการให้นักพัฒนาซอฟต์แวร์ที่ใช้ไคลเอ็นต์ API คิดว่าพวกเขาสามารถกำหนดสิ่งต่างๆให้กับพร็อพเพอร์ตี้ได้
Andrey

2

คุณสมบัติที่มีแอตทริบิวต์ DataMember ต้องมีการตั้งค่าเสมอ คุณควรเขียนออบเจ็กต์ที่คล้ายคลึงกันบนแอปพลิเคชันไคลเอนต์เนื่องจากสมาชิก DataContract สามารถกำหนดค่าได้ตลอดเวลา


2

ฉันมีปัญหากับ ASP.NET MVC และฉันต้องการใช้ DataContractSerializer เพื่อให้สามารถควบคุมชื่อบนรายการในเอาต์พุต JSON ในที่สุดฉันก็เปลี่ยน serializer เป็น JSON.NET ซึ่งรองรับคุณสมบัติที่ไม่มีตัวตั้งค่า (ซึ่ง DataContractSerializer ไม่มี) และการควบคุมชื่อคุณสมบัติ (ซึ่งซีเรียลไลเซอร์ JSON ในตัวใน ASP.NET MVC ไม่ได้) ผ่าน[JsonProperty(PropertyName = "myName")].


2

หากเป็นตัวเลือกที่ทำงานได้แทนที่จะมีErrorBaseเป็นคลาสพื้นฐานให้กำหนดเป็นดังนี้:

    public interface IError
    {
        string Message
        {
            [OperationContract]
            get;

            // leave unattributed
            set;
        }
    }

ตอนนี้แม้ว่าจะมี setter อยู่ แต่ก็ไม่สามารถเข้าถึงไคลเอนต์ผ่านช่องทาง WCF ได้ดังนั้นมันจึงเหมือนกับว่ามันเป็นส่วนตัว


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