WCF cuộn cảm trên các thuộc tính không có "set". Bất kỳ giải pháp nào?


97

Tôi có một số lớp mà tôi đang truyền do kết quả của một phương thức dịch vụ và lớp đó có thuộc tính chỉ nhận:

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

Tôi nhận được một ngoại lệ về phía dịch vụ:

System.Runtime.Serialization.InvalidDataContractException: Không có phương thức đặt cho thuộc tính 'Thông báo' trong loại 'MyNamespace.ErrorBase'.

Tôi phải có thuộc tính này là getter duy nhất, tôi không thể cho phép người dùng gán giá trị cho nó. Bất kỳ giải pháp nào tôi có thể sử dụng? Hay tôi thiếu một số thuộc tính bổ sung?

Câu trả lời:


106

Cung cấp cho Message một getter công khai nhưng setter được bảo vệ, để chỉ các lớp con (và DataContractSerializer, vì nó gian lận :) có thể sửa đổi giá trị.


Đó là một giải pháp gọn gàng!
Russell

Cảm ơn, rất vui vì nó hữu ích! Đây thực sự chỉ là một trong số những cách sử dụng thủ thuật này. Vì getters và setters là các hàm về mặt kỹ thuật, bạn cũng có thể sử dụng kỹ thuật tương tự này để cung cấp tuần tự hóa tùy chỉnh các kiểu nguyên thủy (có lẽ là định dạng thời gian tùy chỉnh trong XML) mà không cần sử dụng IDataContractSurrogate đáng sợ.
rh.

28
Bạn thậm chí có thể đặt nó ở chế độ riêng tư. Serializer không quan tâm đến việc nó là riêng tư, công khai, được bảo vệ, nội bộ hay được bảo vệ nội bộ.
Abel

8
và thực hiện người dàn xếpthrow new NotSupportedException()
Simon_Weaver

2
Có một private set;tác phẩm nếu bạn sử dụng [DataContract][DataMember]. Nếu bạn bỏ qua chúng, bạn cần public set;.
user276648 19/07/17

12

Ngay cả khi bạn không cần cập nhật giá trị, bộ cài đặt được WCFSerializer sử dụng để giải không khí đối tượng (và đặt lại giá trị).

Đây là những gì bạn đang theo đuổi: WCF DataContracts


1
Vì vậy, cách duy nhất để tôi khắc phục vấn đề là biến nó thành một phương thức thay vì tài sản? Một lần nữa, tôi không thể cho phép "đặt" trên thuộc tính này
Andrey

Ngoài ra, bạn có thể đặt nó thành một phương thức (ví dụ: GetMessage () {return "";}), tôi khá chắc chắn rằng bạn có thể yêu cầu WCF Serializer bỏ qua nó. Tôi sẽ xem những gì tôi có thể tìm thấy và cho bạn biết.
Russell

1
Câu hỏi về stackoverflow này đánh trúng cái đinh trên đầu: stackoverflow.com/questions/172681/wcf-datacontracts
Russell

11
[DataMember(Name = "PropertyName")]
public string PropertyName
{
    get
    {
        return "";
    }
    private set
    { }
}

5

Nếu bạn chỉ có một getter, tại sao bạn cần phải tuần tự hóa tài sản. Có vẻ như bạn có thể xóa thuộc tính DataMember cho thuộc tính chỉ đọc và bộ tuần tự hóa sẽ bỏ qua thuộc tính này.


3
Thực sự không có ý nghĩa khi tuần tự hóa một thuộc tính dẫn xuất (ví dụ: thuộc tính URL được tính từ thuộc tính ID) thành một bộ lưu trữ liên tục (ví dụ: cơ sở dữ liệu) - ủng hộ cho điều đó - nhưng việc tuần tự hóa nó thành một biểu diễn (ví dụ: JSON hoặc XML) được trả về bởi một yêu cầu API.
Florian Winter

3

Bạn không thể chỉ có một setter "không làm gì" ??

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

Hay bộ nối tiếp DataContract cũng có barf ở đó ??


14
Nó không thành vấn đề, tôi chỉ không muốn để các nhà phát triển sử dụng API ứng dụng khách nghĩ rằng họ có thể gán nội dung cho thuộc tính.
Andrey

2

Thuộc tính có thuộc tính DataMember luôn yêu cầu thiết lập. Bạn nên viết lại đối tượng simmilar trên ứng dụng khách vì các thành viên DataContract luôn có thể được gán giá trị.


2

Tôi đã gặp sự cố này với ASP.NET MVC và tôi muốn sử dụng DataContractSerializer để có thể kiểm soát tên trên các mục trong đầu ra JSON. Cuối cùng, tôi đã chuyển bộ nối tiếp sang JSON.NET, hỗ trợ các thuộc tính không có bộ định tuyến (mà DataContractSerializer không có) và kiểm soát tên thuộc tính (mà bộ nối tiếp JSON tích hợp trong ASP.NET MVC không có) thông qua [JsonProperty(PropertyName = "myName")].


2

Nếu đó là một tùy chọn khả thi, thì thay vì có ErrorBasedưới dạng lớp cơ sở, hãy xác định nó như sau:

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

            // leave unattributed
            set;
        }
    }

Bây giờ, mặc dù đã tồn tại một bộ cài đặt, nhưng nó không thể truy cập được vào máy khách qua kênh WCF, vì vậy nó như thể nó là riêng tư.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.