2012-10-30 33 views
6

Tôi đã có mã này:Bỏ qua loại chưa biết khi deserializing xml

[XmlType("Metadata")] 
[Serializable] 
public class MetadataContainer : List<MetadataBase> 
{ 
} 

[XmlType("Meta")] 
[XmlInclude(typeof(ReadonlyMetadata))] 
[Serializable] 
public abstract class MetadataBase 
{ 
} 

[XmlType("Readonly")] 
[Serializable] 
public class ReadonlyMetadata : MetadataBase 
{ 
} 

[TestFixture] 
public class SerializationTests 
{ 
    [Test] 
    public void Can_deserialize_with_known_type() 
    { 
     const string text = @"<Metadata xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""> 
         <Meta xsi:type=""Readonly"" /> 
        </Metadata>"; 

     var serializer = new XmlSerializer(typeof(MetadataContainer)); 
     var metas = (MetadataContainer)serializer.Deserialize(XmlReader.Create(new StringReader(text))); 

     Assert.That(metas.Count, Is.EqualTo(1)); 
     Assert.That(metas.First(), Is.InstanceOf<ReadonlyMetadata>()); 
    } 

    [Test] 
    public void Can_deserialize_with_unknown_type() 
    { 
     const string text = @"<Metadata xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""> 
         <Meta xsi:type=""Hello"" /> 
        </Metadata>"; 

     var serializer = new XmlSerializer(typeof(MetadataContainer)); 
     var metas = (MetadataContainer)serializer.Deserialize(XmlReader.Create(new StringReader(text))); 

     Assert.That(metas.Count, Is.EqualTo(0)); 
    } 
} 

Các thử nghiệm đầu tiên hoạt động, nhưng khi tôi chạy thứ hai tôi nhận được lỗi này:

System.InvalidOperationException : There is an error in XML document (2, 9). ----> System.InvalidOperationException : The specified type was not recognized: name='Hello', namespace='', at .

Thay vì nhận được này lỗi Tôi muốn nó bỏ qua các loại không được công nhận. Có cách nào để làm điều này không?

+0

Tôi nghĩ đây sẽ là một trường hợp đăng ký vào một hoặc nhiều của [ 'sự kiện Unknown'-] (http://msdn.microsoft.com/en-us/ thư viện/0a51hxdw.aspx), nhưng trên thử nó có vẻ như không giúp đỡ. Bí ẩn. – AakashM

+0

Tôi cũng nghĩ rằng, kết quả là đáng sợ mặc dù. Mặc dù vậy, tôi đã không tìm được giải pháp. – flindeberg

Trả lời

3

giải pháp chung cho các vấn đề tương tự:

Có một cái nhìn tại unknown element event (link)unknown attribute event (link) và xem họ giải quyết vấn đề, hay chúng ta phải có được bẩn. Đọc ...

giải pháp làm việc cho vấn đề này

Gấu nhớ rằng tôi không có ý tưởng những gì nhiệm vụ của bạn là, AFAIK nó được serializing xml vào datastructure của bạn. Nếu bạn có thể thay đổi datastructure tôi sẽ khuyên bạn nên có một cái nhìn tại Linq2XML và tạo ra một nhà máy thông minh cho các mục đích của bạn.

[TestMethod] 
public void TestLinq2Xml() 
{ 
    const string text = @"<Metadata xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""> 
          <Meta xsi:type=""Readonly"" /> 
          <Meta xsi:type=""Garbage"" /> 
         </Metadata>"; 

    // Get the "names" of all implementors of MetadataBase 
    var types = AppDomain.CurrentDomain.GetAssemblies().ToList() 
    .SelectMany(s => s.GetTypes()) 
     .Where(p => typeof(MetadataBase).IsAssignableFrom(p) && !p.IsAbstract && !p.IsInterface) 
     .Where(t => t.GetCustomAttributes(typeof(XmlTypeAttribute), false).Any()) 
     .Select(t => t.GetCustomAttributes(typeof(XmlTypeAttribute), false) 
      .Cast<XmlTypeAttribute>().First().TypeName); 

    // Create a parser 
    var parser = new XmlSerializer(typeof(MetadataBase)); 

    // Create metadatacontainer to fill 
    var metas = new MetadataContainer(); 
    // Fill it with matching from from the XML 
    metas.AddRange((from t in XDocument.Parse(text).Descendants("Meta") 
       where types.Contains(t.Attribute(XName.Get("type", "http://www.w3.org/2001/XMLSchema-instance")).Value) 
       select (MetadataBase)parser.Deserialize(t.CreateReader())).ToList()); 

    // Should be one guy present 
    Assert.AreEqual(metas.Count, 1); 
} 
0

Bắt tất cả các phần tử không xác định trong một mảng. Bạn vẫn có thể làm việc với họ và cố gắng deserialize sau này, nhưng điều này cho phép deserialization để hoàn thành. Bạn sẽ cần điều này trong mỗi lớp bạn xác định để deserialize các yếu tố của bạn, nơi bạn nghi ngờ sẽ có các yếu tố không rõ.

mỗi http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlanyelementattribute.aspx:

Public Class XClass 
    ' Apply the XmlAnyElementAttribute to a field returning an array 
    ' of XmlElement objects. 
    <XmlAnyElement()> Public AllElements() As XmlElement 
End Class 'XClass 
+1

Lợi ích là tốt nhưng hãy để lại phản hồi để giúp tôi sửa lại câu trả lời của mình. – VoteCoffee

+0

Câu trả lời rất thú vị. Sẽ phải thử điều đó. – AnthonyVO

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