2012-02-17 30 views
11

tôi cần phải khởi tạo lĩnh vực readonly tin sau Deserialization. Tôi có folowing DataContract:Khởi lĩnh vực readonly tin sau deserializing

[DataContract] 
public class Item 
{ 
    public Item() 
    { 
     // Constructor not called at Deserialization 
     // because of FormatterServices.GetUninitializedObject is used 
     // so field will not be initialized by constructor at Deserialization 
     _privateReadonlyField = new object(); 
    } 

    // Initialization will not be called at Deserialization (same reason as for constructor) 
    private readonly object _privateReadonlyField = new object(); 

    [DataMember] 
    public string SomeSerializableProperty { get; set; } 

    [OnDeserializing] 
    public void OnDeserializing(StreamingContext context) 
    { 
     // With this line code even not compiles, since readonly fields can be initialized only in constructor 
     _privateReadonlyField = new object(); 
    } 
} 

Tất cả những gì tôi cần, sau khi Deserialization _privateReadonlyField không phải là rỗng.

Mọi góp ý về vấn đề này - là nó có thể ở tất cả? Hoặc tôi cần xóa khóa "chỉ đọc", đây không phải là lựa chọn tốt.

+0

Bạn đang sử dụng phương pháp tuần tự nào? Việc xây dựng các đối tượng khác nhau cho các phương pháp khác nhau. –

+0

Có gì sai với đánh dấu của bạn '_privateReadonlyField' một' [DataMember] '? Serializer hợp đồng dữ liệu sẽ chăm sóc nó mà không có một vấn đề. – dasblinkenlight

+0

Joachim Isaksson: Tôi đang sử dụng DataContractJsonSerializer nhưng thực sự điều này không quan trọng - tất cả các Serializers sử dụng FormatterServices.GetUninitializedObject khi Deserializing. – Andris

Trả lời

7

Bất kỳ lĩnh vực khai báo là private readonly có thể được khởi tạo trong cùng một dòng, nơi nó được tuyên bố hoặc bên trong một constructor. Khi đã xong, nó không thể thay đổi.

Từ MSDN:

Các từ khóa readonly là một modifier mà bạn có thể sử dụng trên đồng ruộng. Khi một khai báo trường bao gồm một công cụ sửa đổi chỉ đọc, các phép gán cho các trường được giới thiệu bởi khai báo chỉ có thể xảy ra như một phần của khai báo hoặc trong một hàm tạo trong cùng một lớp.

Điều đó có nghĩa là bạn sẽ phải xóa readonly từ khóa để làm cho từ khóa hoạt động.

+0

Cảm ơn, Huske. Thật không may bạn đã chấp nhận cảm giác của tôi về điều này, tôi hy vọng rằng một số cách tồn tại để giải quyết vấn đề này. – Andris

8

serialization có thể đọc trong các giá trị cho các lĩnh vực chỉ đọc vì nó sử dụng phản chiếu, mà bỏ qua quy tắc khả năng tiếp cận. Có thể lập luận rằng sau đây, được chứng minh là một phần của quá trình tuần tự hóa, mặc dù tôi khuyên bạn nên chống lại nó trong hầu hết mọi trường hợp khác:

private readonly Doodad _oldField; 

[OptionalField(VersionAdded = 2)] 
private readonly Widget _newField; 

[OnDeserialized] 
private void OnDeserialized(StreamingContext context) 
{ 
    if (_oldField != null && _newField == null) 
    { 
     var field = GetType().GetField("_newField", 
      System.Reflection.BindingFlags.Instance | 
      System.Reflection.BindingFlags.DeclaredOnly | 
      System.Reflection.BindingFlags.NonPublic); 
     field.SetValue(this, new Widget(_oldField)); 
    } 
} 
+1

Cảm ơn bạn đã trả lời. Tôi thực sự quên mất sự phản chiếu, khi được hỏi câu hỏi. – Andris

+0

Thuộc tính '[OptionalField]' có tác dụng gì đối với giải pháp này? Có 'OnDeserialized' vẫn hoạt động mà không có nó? –

+0

Nếu tôi nhớ chính xác, việc bỏ qua nó sẽ khiến cho quá trình deserialization ném một ngoại lệ khi đọc đầu vào không chứa trường đó. –

Các vấn đề liên quan