WCF tersedak properti tanpa "set". Ada solusi?

97

Saya memiliki beberapa kelas yang saya lewati sebagai hasil dari metode layanan, dan kelas itu memiliki properti get-only:

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

Saya mendapatkan pengecualian di sisi layanan:

System.Runtime.Serialization.InvalidDataContractException: Tidak ada metode yang ditetapkan untuk properti 'Message' dalam jenis 'MyNamespace.ErrorBase'.

Saya harus menjadikan properti ini sebagai pengambil saja, saya tidak dapat mengizinkan pengguna untuk menetapkan nilainya. Ada solusi yang bisa saya gunakan? Atau apakah saya kehilangan beberapa atribut tambahan?

Andrey
sumber

Jawaban:

107

Berikan Message getter publik tetapi penyetel yang dilindungi, sehingga hanya subclass (dan DataContractSerializer, karena ia menipu :) yang dapat mengubah nilainya.

rh.
sumber
Itu adalah solusi yang bagus!
Russell
Terima kasih, senang itu berguna! Ini sebenarnya hanyalah salah satu dari beberapa kegunaan trik ini. Karena getter dan setter secara teknis berfungsi, Anda juga dapat menggunakan teknik yang sama ini untuk menyediakan serialisasi kustom tipe primitif (mungkin format waktu kustom dalam XML) tanpa perlu menggunakan IDataContractSurrogate yang mengintimidasi.
rh.
28
Anda bahkan bisa membuatnya pribadi. Serializer tidak keberatan apakah itu pribadi, publik, dilindungi, internal atau internal terlindungi.
Abel
8
dan membuat penyetelthrow new NotSupportedException()
Simon_Weaver
2
Memiliki private set;karya jika Anda menggunakan [DataContract]dan [DataMember]. Jika Anda menghilangkannya, Anda membutuhkannya public set;.
pengguna276648
12

Bahkan jika Anda tidak perlu memperbarui nilai, penyetel digunakan oleh WCFSerializer untuk deserialisasi objek (dan menyetel ulang nilainya).

SO ini adalah apa yang Anda kejar: WCF DataContracts

Russell
sumber
1
Jadi satu-satunya cara bagi saya untuk mengatasi masalah ini adalah menjadikannya metode alih-alih properti? Sekali lagi, saya tidak bisa mengizinkan "set" di properti ini
Andrey
Anda bisa menjadikannya sebuah metode (misalnya GetMessage () {return "";}) sebagai alternatif, saya cukup yakin Anda bisa memberitahu WCF Serializer untuk mengabaikannya. Saya akan melihat apa yang dapat saya temukan dan memberi tahu Anda.,
Russell
1
Pertanyaan stackoverflow ini tepat sasaran: stackoverflow.com/questions/172681/wcf-datacontracts
Russell
11
[DataMember(Name = "PropertyName")]
public string PropertyName
{
    get
    {
        return "";
    }
    private set
    { }
}
Rikin Patel
sumber
5

Jika Anda hanya memiliki getter, mengapa Anda perlu membuat serial properti sama sekali. Sepertinya Anda bisa menghapus atribut DataMember untuk properti read-only, dan serializer akan mengabaikan properti tersebut.

Rob Lambert
sumber
3
Memang tidak masuk akal untuk membuat serialisasi properti turunan (misalnya, properti URL yang dihitung dari properti ID) ke penyimpanan persisten (misalnya, database) - upvote untuk itu - tetapi masuk akal untuk membuat serialisasi ke representasi (misalnya, JSON atau XML) yang dikembalikan oleh permintaan API.
Florian Winter
4

Tidak bisakah Anda memiliki setter "tidak melakukan apa-apa" ??

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

Atau apakah barf serializer DataContract juga?

marc_s
sumber
14
Itu tidak muntah, saya hanya tidak ingin membiarkan pengembang yang menggunakan API klien berpikir bahwa mereka dapat menetapkan barang ke properti.
Andrey
2

Properti dengan atribut DataMember selalu memerlukan set. Anda harus menulis ulang objek serupa pada aplikasi klien karena anggota DataContract selalu dapat diberi nilai.

Jojo Sardez
sumber
2

Saya memiliki masalah ini dengan ASP.NET MVC dan saya ingin menggunakan DataContractSerializer agar dapat mengontrol nama pada item dalam output JSON. Akhirnya saya beralih serializer ke JSON.NET, yang mendukung properti tanpa setter (yang DataContractSerializer tidak) dan kontrol nama properti (yang tidak dimiliki serializer JSON bawaan di ASP.NET MVC) [JsonProperty(PropertyName = "myName")].

Thomas Lundström
sumber
2

Jika ini adalah opsi yang layak, alih-alih menjadikannya ErrorBasesebagai kelas dasar, tentukan sebagai berikut:

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

            // leave unattributed
            set;
        }
    }

Sekarang, meskipun ada penyetel, itu tidak dapat diakses oleh klien melalui saluran WCF, jadi seolah-olah itu pribadi.

Gilad
sumber