2011-12-27 17 views
5

Tôi có cấu trúc đối tượng mà tôi đang cố gắng tuần tự hóa thành xml dẫn đến mức nút trùng lặp. Tôi khá chắc chắn nó có một cái gì đó để làm với subclassing bởi vì tôi đã phải thực hiện deserialization của riêng tôi nhưng tôi không chắc chắn chính xác những gì đang xảy ra theo hướng khác. Cấu trúc xml tương tự được sử dụng làm đầu vào khi deserializing dữ liệu của tôi lúc khởi động ứng dụng như khi reserializing nó được lưu sau này.Kết quả tuần tự hóa XML trong các nút trùng lặp

Đây là những gì đầu ra xml bị lỗi trông giống như:

<Keyboarding xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Exercises> 
    <Exercise> 
     <Exercise Id="3" ActivityNumber="5" SubActivityNumber="b" Type="Standard"> 
     <Title>Test Title</Title> 
     <Instructions>Downloaded Update Instructions</Instructions> 
     </Exercise> 
    </Exercise> 
    </Exercises> 
</Keyboarding> 

Đây là những gì nó sẽ giống như thế (và trông giống như trên deserialization ban đầu):

<Keyboarding xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Exercises> 
     <Exercise Id="3" ActivityNumber="5" SubActivityNumber="b" Type="Standard"> 
     <Title>Test Title</Title> 
     <Instructions>Downloaded Update Instructions</Instructions> 
     </Exercise> 
    </Exercises> 
</Keyboarding> 

Đối tượng gốc chứa một bộ sưu tập các bài tập . Bài tập là lớp cơ sở của tôi, trong khi các lớp con được xác định bởi thuộc tính Type. Tôi đang sử dụng serializer xml tùy chỉnh để xây dựng các đối tượng của các kiểu có nguồn gốc khác nhau từ Bài tập vì nó cho phép tôi sử dụng sự phản chiếu để phù hợp với bất kỳ loại nào trong số 2 hoặc nhiều loại tiềm năng có nguồn gốc, theo thứ tự và số lượng chưa biết khi đọc lần đầu tiên bởi ứng dụng của tôi.

Dưới đây là bộ sưu tập các phần tử gốc, sử dụng giao serializer tùy chỉnh xml:

[XmlArray("Exercises")] 
[XmlArrayItem("Exercise", Type = typeof (ExerciseXmlSerializer<Exercise>))] 
public Collection<Exercise> UnprocessedExercises { get; set; } 

lớp tập thể dục cơ sở của tôi được khai báo như sau:

[Serializable] 
[XmlType(AnonymousType = true)] 
public class Exercise 

Và lớp được thừa kế của tôi được khai báo như sau:

[Serializable] 
[XmlType(AnonymousType = true)] 
[XmlRoot(ElementName = "Exercise", IsNullable = false)] 
public class StandardExercise : Exercise 

Đây là phần ghi của trình theo dõi xml tùy chỉnh của tôi:

public class ExerciseXmlSerializer<T> : IXmlSerializable where T : class 
{ 
    private T _data; 
    ... 
    public void WriteXml(XmlWriter writer) 
    { 
     Type type = _data.GetType(); 

     new XmlSerializer(type).Serialize(writer, _data); 
    } 
    ... 
} 

Trong phương thức WriteXml(), biến kiểu được đặt đúng theo kiểu dẫn xuất, vậy tại sao nó tạo cấp nút cho cả loại cơ sở và kiểu dẫn xuất? Làm thế nào để ngăn chặn nó làm như vậy?

Trả lời

1

Tôi nghĩ vấn đề của bạn là với dòng này:

[XmlArrayItem("Exercise", Type = typeof (ExerciseXmlSerializer<Exercise>))] 

Tôi không nghĩ rằng bạn muốn chỉ ra rằng các loại mặt hàng là một loại serializer. Nếu bạn muốn thực hiện IXmlSerializable, nó cần phải được trên lớp để được serialized.

Dưới đây là những gì tôi đã làm việc:

public class Keyboarding 
{ 
    [XmlArray("Exercises")] 
    [XmlArrayItem("Exercise")] 
    public Collection<Exercise> UnprocessedExercises { get; set; } 

    public Keyboarding() 
    { 
     UnprocessedExercises = new Collection<Exercise>(); 
     UnprocessedExercises.Add(new StandardExercise()); 
    } 
} 

[XmlInclude(typeof(StandardExercise))] 
public class Exercise 
{ 
} 
[Serializable] 
public class StandardExercise : Exercise 
{ 
} 

này tạo ra đầu ra tương tự như sau:

<?xml version=\"1.0\"?> 
<Keyboarding xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> 
    <Exercises> 
    <Exercise xsi:type=\"StandardExercise\" /> 
    </Exercises> 
</Keyboarding> 

Nếu bạn không muốn xsi:type bao gồm trong đầu ra, bạn có thể sử dụng câu trả lời cho this question.

+0

Định dạng như các ngắt như vậy khi tôi đang cố gắng deserialize dữ liệu ban đầu, có cùng định dạng xml. Khi tôi sửa đổi mã và xml ban đầu để phù hợp với mã của bạn, nó đã gõ mọi thứ làm kiểu cơ sở khi deserializing và mất tất cả các lớp con. Tôi đã xác định loại của các mục như là một xizer serializer là bởi vì có gần 2 tá có thể có nguồn gốc các lớp học họ có thể được gõ vào và một số lượng không rõ các mặt hàng và trật tự trong xml. Điều này cho phép tôi lấy thuộc tính Type và sử dụng sự phản chiếu trong serializer tùy chỉnh của tôi để xây dựng các đối tượng có nguồn gốc. Tôi sẽ chỉnh sửa câu hỏi của mình để cố gắng làm rõ một chút. – HotN

+1

@HotN: Bạn đã thử triển khai mã tuần tự tùy chỉnh của mình trực tiếp đến lớp Tập thể dục chưa? Tôi nhận được trường hợp ngoại lệ khi tôi cố gắng chạy mã như nó và nó là 'typeof (ExerciseXmlSerializer )' trong XmlArrayItem đó là gây ra các vấn đề. Bạn cũng có thể thử viết một xmlwriter tùy chỉnh như được hiển thị trong câu trả lời cho câu hỏi được liên kết ở cuối câu trả lời của tôi. –

+0

Vấn đề chắc chắn là do phần 'typeof (ExerciseXmlSerializer )' nhưng điều tôi thấy là việc thay đổi thành Tập thể dục sẽ giải quyết vấn đề tuần tự hóa nhưng sẽ phá vỡ quá trình deserialization của tôi. Tôi đã nhận nó để làm việc cuối cùng bằng cách để lại mã ban đầu tại chỗ cho bộ sưu tập tập thể dục nhưng thực hiện XmlTextWriter của riêng tôi, như bạn đề nghị. Nó cảm thấy giống như một loại giải pháp phức tạp, nhưng tôi làm như vậy nó không yêu cầu tôi liệt kê ra 20 lớp học có nguồn gốc như [XmlInclude]. Dù sao, kết quả là kết quả. Cảm ơn! – HotN

0

Bạn sẽ có thể sử dụng XmlAttributeOverrides để thực hiện những gì bạn đang yêu cầu. Trong trường hợp này, bạn có thể làm một cái gì đó như thế này. Mã mẫu là một chút thô vì bạn không bao gồm toàn bộ đồ thị đối tượng của bạn, nhưng hy vọng điều này sẽ chỉ cho bạn đi đúng hướng.

List<Type> extraTypes = new List<Type>(); 
XmlAttributes attrs = new XmlAttributes(); 

extraTypes.Add(typeof(Exercise)); 
extraTypes.Add(typeof(StandardExercise)); 

XmlElementAttribute attr = new XmlElementAttribute 
{ 
    ElementName = "Exercise", 
    Type = typeof(Exercise) 
}; 
attrs.XmlElements.Add(attr); 

attr = new XmlElementAttribute 
{ 
    ElementName = "StandardExercise", 
    Type = typeof(StandardExercise) 
}; 
attrs.XmlElements.Add(attr); 

XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 
overrides.Add(typeof(Keyboarding), "Keboarding", attrs); 

return new XmlSerializer(typeof(Keyboarding), overrides, extraTypes.ToArray(), 
    new XmlRootAttribute("Keyboarding"), string.Empty); 

Điều này sẽ cho phép bạn tạo cây XML giống như thế này. Nó không phải là những gì bạn đang tìm kiếm, nhưng chỉ là mô tả.

<Keyboarding xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Exercises> 
     <StandardExercise Id="3" ActivityNumber="5" SubActivityNumber="b"> 
      <Title>Test Title</Title> 
      <Instructions>Downloaded Update Instructions</Instructions> 
     </StandardExercise > 
    </Exercises> 
</Keyboarding> 
Các vấn đề liên quan