2012-05-04 89 views
11

Tôi đã gặp phải một số hành vi đáng ngạc nhiên khi sử dụng XmlSerializer trong C#. Hãy xem xét đoạn mã sau đây..NET XmlSerializer và các lớp lồng nhau trong C#

public class A : IEnumerable 
{ 
    public class B 
    { 
     [XmlAttribute] 
     public string PropA { get; set; } 
     [XmlElement] 
     public string PropB { get; set; } 
    } 

    public IEnumerator GetEnumerator() 
    { 
     yield break; 
    } 
} 

class Program 
{ 
    static void Main (string[] args) 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(A.B)); 

     XmlTextWriter writer = new XmlTextWriter(@"E:\temp\test.xml", Encoding.Default); 
     serializer.Serialize(writer, new A.B() { PropA = "one", PropB = "two" }); 
    } 
} 

Trong ví dụ này, tôi cố gắng tuần tự hóa một thể hiện của lớp lồng nhau A.B, chính nó không sử dụng lớp chứa A theo bất kỳ cách nào. Nhưng khi tôi cố gắng để xây dựng các XmlSerializer cho nó, các ngoại lệ sau đây được ném:

InvalidOperationException là unhandled:

Để có XML serializable, loại mà kế thừa từ IEnumerable phải có một thực hiện của chương trình Add (Hệ thống .Object) ở tất cả các cấp của phân cấp thừa kế . Test.A không thực hiện Add (System.Object).

XmlSerializer đang cố gắng áp dụng các ràng buộc serialization đối với loại A khi tôi thực sự cố gắng sắp xếp loại A.B. Tuy nhiên, sự hiểu biết của tôi là ngoài quyền truy cập đặc quyền vào dữ liệu trong các cá thể của kiểu bên ngoài, một kiểu lồng nhau không phải là đặc biệt và hoạt động như thể nó nằm trong một không gian tên.

Sự hiểu biết này không chính xác và làm ngữ nghĩa của các loại lồng nhau hoặc XmlSerializer biện minh cho hành vi này, hoặc điều này có cảm giác giống như một lỗi trong XmlSerializer?

Về vấn đề cụ thể đối với ngữ nghĩa XmlSerializer, có bất kỳ yêu cầu nào về tài liệu thực thi ràng buộc XmlSerializer trên tất cả các kiểu bên ngoài khi được áp dụng với kiểu lồng nhau không?

+1

Bạn không gặp vấn đề với các loại lồng nhau. Lớp A của bạn không có thuộc tính kiểu 'B'. –

+0

Ngoài ra, không sử dụng 'new XmlTextWriter()'. Đó là không được chấp nhận kể từ .NET 2.0. Sử dụng 'XmlWriter.Create()' để thay thế. –

+3

Tôi xin lỗi, nhưng bạn đã bỏ lỡ toàn bộ câu hỏi của tôi. Tôi không cố gắng serialize A, và tôi không cố gắng để serialize B như là một tài sản của A. Tôi đang cố gắng để serialize nó hoàn toàn độc lập của A. Và tôi nhận thức được sự phản đối của TextWriter. Đây là một ví dụ giả vờ ra khỏi đỉnh đầu của tôi mà tôi đã cố giữ ngắn gọn. –

Trả lời

0

đó là IEnumerable đang đặt ra các ràng buộc ở đây. Nếu bạn thêm phương thức Thêm như được đề xuất bởi ngoại lệ, mã của bạn sẽ hoạt động tốt. Một lần nữa điều này có rất ít để làm với XmlSerialization và nhiều hơn nữa với cách IEnumerable hoạt động. Vui lòng sửa tôi nếu tôi ở đây. Kiểm tra this để có một cuộc thảo luận tốt về cùng.

+0

Một lần nữa, tôi biết ràng buộc là gì và cách giải quyết nó. Câu hỏi thực sự là, tại sao ràng buộc này được áp dụng cho một kiểu mà tôi không thực sự cố gắng sắp xếp theo thứ tự. Các ràng buộc khác tôi đã quan sát được là một vấn đề là constructor mặc định, mặc dù tôi đã khó khăn hơn cô lập một ví dụ. –

+0

Justin là chính xác. Đây là một lỗi trong XML Serializer. Đây không phải là vấn đề tương tự như câu hỏi bạn đã liên kết. –

0

Trình XmlSerializer cung cấp điều trị đặc biệt cho các lớp thực hiện IEnumerable hoặc ICollection. hơn

chi tiết tại đây: XmlSerializer and IEnumerable: Serialization possible w/o parameterless constructor: Bug?

+0

Điểm của ví dụ mà tôi cung cấp là lớp triển khai thực hiện IEnumerable không thực sự là lớp được tuần tự hóa. Lớp lồng nhau đang được tuần tự hóa và hoàn toàn độc lập. Tác giả của câu trả lời được chấp nhận của câu hỏi mà bạn đã liên kết cũng dường như đồng ý rằng đây là lỗi. –

1

http://msdn.microsoft.com/en-us/library/vstudio/ms229027%28v=vs.100%29.aspx

Bởi vì một loại lồng nhau được đối xử như một thành viên của kiểu tuyên bố, các loại lồng nhau có quyền truy cập vào tất cả các thành viên khác trong các loại hình tuyên bố.

Vì vậy, nếu serializer muốn làm việc với A.B, nó cũng cần định nghĩa A. Trường hợp đá xác nhận IEnumerable trong.

Không quan trọng rằng B không thực sự đề cập đến bất cứ điều gì trong A :)

0

Có lẽ đây là một vấn đề rất khó khăn trong serialization thời gian chạy nhưng tôi không có bất kỳ lời giải thích tốt cho hành vi này. Tôi cảm thấy như giới hạn của IEnumerable không áp dụng cho lớp B.