2009-12-23 31 views
11

Sử dụng DataContractSerializer serialize đối tượng của tôi, tôi nhận được một đầu ra tương tự nhưCó cách nào để tạo ra XML DataContractSerializer đầu ra sạch hơn không?

<?xml version="1.0" encoding="utf-8" ?> 
<AgentNotification xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/The.name.space.Notifications"> 
    <_x003C_Created_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" /> 
    <_x003C_Id_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" />   
<_x003C_Email_x003E_k__BackingField>[email protected]</_x003C_Email_x003E_k__BackingField> 
    <_x003C_Name_x003E_k__BackingField>Random Person</_x003C_Name_x003E_k__BackingField> 
<_x003C_Policies_x003E_k__BackingField> 
<PolicyNotification> 
    <_x003C_Created_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" /> 
    <_x003C_Id_x003E_k__BackingField i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/The.name.space" /> 
    <_x003C_ConfirmationNumber_x003E_k__BackingField>Some number</_x003C_ConfirmationNumber_x003E_k__BackingField> 
    </PolicyNotification> 
<PolicyNotification> 
    </_x003C_Policies_x003E_k__BackingField> 
    </AgentNotification> 

Có cách nào cho nó để thẻ đầu ra mà chỉ là

<Id> 
<Name> 

vv, mà không cần phải trang trải các lớp học của tôi với các thuộc tính?

Nếu không có cách nào, đầu ra của điều này được đảm bảo giống nhau mỗi lần chính xác? Vì vậy, nếu tôi sử dụng điều này để biểu đồ đối tượng của tôi là XML để trộn với một tài liệu X * để tạo tệp mà tôi sẽ không bao giờ gặp phải vấn đề nơi các nút của tôi thay đổi tên và tài liệu được đưa ra không chính xác?

+3

Không. Và đừng lo lắng về cách xml của bạn trông như thế nào. Nó chỉ dẫn đến đau khổ. – Will

+0

Bạn nên đặt câu trả lời là Will. –

Trả lời

8

Điều này xảy ra vì bạn phải đánh dấu các loại của mình (ví dụ: AgentNotification) với [Serializable]. Khi DataContractSerializer gặp loại được đánh dấu bằng [Serializable] nhưng không rõ ràng [DataContract], nó tạo ra một default contract cho loại khớp với cách BinaryFormatter nối tiếp một lớp, để sắp xếp theo thứ tự all member variables of a class — even variables marked as private - theo tên.Đối với auto-implemented properties, điều này có nghĩa là secret backing fields được đăng theo tên; tên của họ là những tên phần tử đặc biệt mà bạn đang thấy.

Cách dễ nhất để giải quyết vấn đề này là xóa thuộc tính [Serializable] khỏi các lớp học của bạn. Bạn gần như chắc chắn không cần nó trừ khi bạn đang thực sự sử dụng BinaryFormatter hoặc SoapFormatter. Sau khi làm như vậy, DataContractSerializer giờ đây sẽ tuần tự hóa các thuộc tính công khai và các trường của bạn theo tên chứ không phải các trường công khai và riêng tư theo tên.

+0

Điều đó có lẽ sẽ là những gì tôi muốn 6 năm trước đây. Nhưng tại một số điểm tôi chỉ dừng sử dụng XSLT và bắt đầu sử dụng Postal + RazorViewEngine để tạo nội dung email. –

1

DataContractSerializer sẽ tuần tự hóa tất cả các thuộc tính công khai (nếu bạn không chỉ định bất kỳ thứ gì - có thể là .NET 3.5 SP1) hoặc (cách tiếp cận tôi thích) bất kỳ thứ gì bạn gắn nhãn với thuộc tính [DataMember]. Vì vậy, điều tốt nhất bạn có thể làm là đánh dấu lớp học của bạn với thuộc tính [DataContract] và tất cả các thành viên (thuộc tính, trường, v.v.) mà bạn thực sự muốn trong hợp đồng dữ liệu của mình với thuộc tính [DataMember].

Các DataContractSerializer không thực sự cho phép kiểm soát nhiều hơn thế - bạn có thể xác định khá rõ ràng (sử dụng rõ ràng "opt-in" phương pháp này) được đăng, nhưng bạn có ít hoặc không kiểm soát cách nó được tuần tự hóa.

Nhưng bạn có thực sự cần điều đó không? CÓ THẬT KHÔNG? Nếu có, có thể bạn sẽ phải sử dụng XmlSerializer cho quá trình tuần tự hóa đó - bạn có thể kiểm soát nhiều hơn cách những thứ được tuần tự hóa (nhưng là một nhược điểm, XmlSerializer sẽ tuần tự hóa mọi thuộc tính công cộng không phải là được đánh dấu rõ ràng với thuộc tính [XmlIgnore] - một lược đồ "chọn không tham gia").

Kiểm tra Dan Rigsby blog post về sự khác biệt giữa DataContractSerializer và XmlSerializer và những gì mỗi người trong số họ cung cấp.

+0

Tôi muốn nó tuần tự hóa tất cả các thuộc tính, XMLSerializer thậm chí không phải là một tùy chọn vì đối tượng của tôi có một IList trong đó. Tôi đã hỏi về lược đồ đặt tên vì nó sẽ dễ dàng hơn trong tài liệu biến đổi của tôi nếu các thuộc tính khớp chính xác với các đối tượng lớp của tôi. –

+0

bạn đã trang trí lớp học và các thuộc tính của mình với các thuộc tính [DataMember] chưa? Bạn có thể định nghĩa tên với những tên đó: [DataMember (Name = "xyz")] - điều đó có giúp ích gì trong trường hợp của bạn không? –

+0

bạn đã trang trí các lớp học sẽ kết thúc bên trong IList của bạn với thuộc tính [DataContract] và [DataMember] chưa? Nó gần giống như bạn không ... –

5

Tên phần tử dài (chẳng hạn như _x003C_Created_x003E_k__BackingField) được tạo bởi .NET khi bạn sử dụng tính năng tự động phát.

Nếu bạn thay đổi chúng thành thuộc tính có trường sao lưu, thay vào đó chúng sẽ sử dụng tên trường sao lưu của bạn. Bạn có thể làm điều đó mà không cần thêm bất kỳ thuộc tính nào vào mã của mình.

(Ngoài ra, bạn chỉ cần thêm một [DataContract] thuộc tính để định nghĩa lớp học của bạn sẽ dọn dẹp XML của bạn rất nhiều - mặc dù không hoàn toàn.)

+0

Tôi sẽ phải kiểm tra sự khác biệt nào, tôi có thể chấp nhận việc đặt một thuộc tính ở cấp lớp đặc biệt là vì các lớp này là datacontracts ngay cả khi chúng không được tiếp xúc qua WCF –

+1

Tôi quan tâm đến kinh nghiệm của bạn. Tuần tự hóa dường như được xác định kém và bị nhiều giải pháp. –

0

tôi gặp những rắc rối tương tự, cuối cùng, vì vậy bạn chỉ cần để thêm [DataContract] 和 [DataMember] vào mô hình.

+1

Câu trả lời này được tự động gắn cờ là chất lượng thấp vì độ dài và nội dung của nó. [Brevity là chấp nhận được, nhưng giải thích đầy đủ hơn là tốt hơn.] (Http://stackoverflow.com/help/how-to-answer) –

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