2009-02-22 30 views
46

Đây là một trong những tôi đấu tranh với lứa tuổi vì vậy nghĩ rằng tôi muốn tài liệu ở đâu đó. (Xin lỗi để hỏi và trả lời một câu hỏi.)Tại sao tài sản công cộng của tôi không được XmlSerializer tuần tự hóa?

(C# .net 2.0) Tôi đã có một lớp đã được xê-ri hóa bởi XmlSerializer, tôi đã thêm một thuộc tính công khai mới tuy nhiên nó không được đưa vào XML đầu ra.

Nó không được đề cập trong tài liệu ở bất cứ nơi nào tôi có thể tìm thấy, nhưng các thuộc tính công khai phải có một bộ cũng như được sắp xếp theo thứ tự! Tôi đoán điều này là bởi vì nó giả định rằng nếu bạn đang đi để serialize sau đó bạn sẽ muốn deserialize từ cùng một tập tin, do đó, chỉ serializes tài sản có cả một tập hợp và nhận được một.

Trả lời

76

Như đã đề cập, hầu hết các thuộc tính phải có cả getter và setter; ngoại lệ chính cho danh sách này - ví dụ:

private readonly List<Foo> bar = new List<Foo>(); 
public List<Foo> Bar {get { return bar; } } // works fine 

sẽ hoạt động tốt; tuy nhiên, nếu XmlSerializertìm thấy một người đặt cược - yêu cầu đó là công khai; sau đây sẽ không công việc:

public List<Foo> Bar {get; private set;} // FAIL 

lý do khác nó có thể không serialize:

  • nó không phải là công khai với get và set (hoặc là readonly cho một lĩnh vực)
  • nó có thuộc tính [DefaultValue] và có giá trị đó
  • nó có phương thức công khai bool ShouldSerializeFoo() trả về false
  • nó có một công bool FooSpecified {get;set;} bất động sản hoặc trường đó quay trở lại sai
  • nó được đánh dấu [XmlIgnore]
  • nó được đánh dấu [Obsolete]

Bất kỳ trong số này sẽ gây ra nó không để serialize

+0

Mặc dù tôi có một số thuộc tính chỉ với mục đích. Chúng cũng được đánh dấu bằng các thuộc tính XmlArray và XmlArrayItem, vì vậy tôi đoán đó là lý do tại sao chúng thoát ra ngoài với một tập hợp. – Rory

+2

Trong một số trường hợp, thuộc tính trả về bộ sưu tập không cần bộ, nhưng nó phải được khởi tạo trong hàm tạo ... Đây là trường hợp cho các bộ sưu tập không có hàm tạo công khai. Nhưng hành vi này có vẻ hơi không phù hợp với tôi ... –

+0

Tôi chưa bao giờ để ý điều đó, cảm ơn Thomas; Tôi sẽ điều tra ;-p –

7

Điểm về getter + setter được thực hiện trong đoạn thứ 3 trên trang "Intro to Xml Serialization". Đó là thực sự trong một hộp gọi ra. Không thể bỏ lỡ nó!

Intro-to-XML Serialization http://www.freeimagehosting.net/uploads/2f04fea2db.png

(có một chút quá nhiều niềm vui với Freeimagehosting.net)

+0

ah, bạn nói đúng là nó có nhưng sai rằng bạn không thể bỏ lỡ nó :) – Rory

+0

Tôi đọc về một nghiên cứu một lần, cho biết mọi người bỏ qua tiêu đề và gọi ra các hộp trong bài viết, thường xuyên hơn họ bỏ qua các văn bản thông thường. ?? Số lượt truy cập hiệu quả. – Cheeso

+0

@ Cheeso: đúng vậy, tôi chưa bao giờ xem các liên kết được tài trợ trong kết quả tìm kiếm của Google;) –

4

Cũng thuộc tính trả về null không được đăng!

+1

Ah, nhưng các thuộc tính kiểu nullable trả về null là! Tôi có điều này ở đây công cộng int? Thuộc tính GroupTypeId đã được tuần tự hóa thành XML ở đây - Jon

2

Và nếu lớp của bạn kế thừa danh sách và cũng có các thành viên riêng, chỉ các phần tử của danh sách được đăng theo thứ tự. Dữ liệu có trong các thành viên trong lớp của bạn không bị bắt. Mất chút thời gian để tìm hiểu điều này!

+0

Ah, nhưng tại sao? Có ai biết không? – almcnicoll

5

nếu bạn không muốn triển khai trình xử lý thích hợp (vì có thể bạn không muốn deserialize hoặc thay đổi giá trị đối tượng), bạn chỉ có thể sử dụng trình cài đặt giả như thế này set { }, sao cho công việc XMLSerializer sử dụng Setter ...

iE

public string ID { get { return _item.ID.ToString(); } set { } } 
+2

điều này có khả năng có thể là một vấn đề nếu một lập trình viên cơ sở sử dụng thuộc tính setter này và nghĩ rằng nó thiết lập giá trị. Vẫn muốn có "ném ngoại lệ mới ..." – user384080

1

Một điều nữa để thêm khoảng serialization của bộ sưu tập:

XmlSerializer bỏ qua bộ sưu tập giao diện!

Và theo đó tôi có nghĩa là bỏ qua. Trong khi bạn sẽ nhận được một ngoại lệ cho một dòng như:

public IFoo Foo { get; set; } 

bạn sẽ không có được một ngoại lệ cho:

public ICollection<IFoo> LotsOfFoos { get { return this.fooBackingField; } } 
0

Bạn có thể thực hiện các IXmlSerializer và thực hiện tuần tự bằng tay, và được hưởng lợi từ serializing và ngược lại, deserializing chúng bằng cách sử dụng constructors/private field assignment.

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