0

如何反序列化xml忽略节点类型的差异,即成员是表示为XmlElement还是表示为XmlAttribute。如何反序列化xml忽略节点类型中的差异(即是否XmlElement或XmlAttribute)

例如,我有这样的XML源

<Book> 
    <Title>Introduction to c#</Title> 
    <Publisher>John Smith</Publisher> 
    <Year>2012</Year> 
<Book> 

而且我想使用这个类

public class Book 
{ 
    public string Title{ get; set; } 

    [XmlAttribute()] 
    public string Publisher{ get; set; } 

    [XmlAttribute()] 
    public string Year{ get; set; } 
} 

反序列化它,你可以看到出版商和年份都标有“[XmlAttribute ]“在类中,所以它们不被反序列化。

有没有办法告诉反序列化器忽略成员表示为属性还是元素的差异?

我需要这在一个通用的转换器将一种类型转换到另一种相似类型

 public static Type2 ConvertType1ToType2<Type1, Type2>(Type1 type1) 
     { 
      using (MemoryStream objectStream = new MemoryStream()) 
      { 
       XmlSerializer type1Serializer = new XmlSerializer(typeof(Type1)); 
       XmlSerializer type2Deserializer = new XmlSerializer(typeof(Type2)); 

       type1Serializer.Serialize(objectStream, type1); 
       objectStream.Position = 0; 

       return (Type2)type2Deserializer.Deserialize(objectStream); 
      } 
     } 

回答

1

这种尝试,

string sXml = @"<Book> 
          <Title>Introduction to c#</Title> 
          <Publisher>John Smith</Publisher> 
          <Year>2012</Year> 
          </Book>"; 

      XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 

      XmlAttributes PublisherAttributes = new XmlAttributes(); 
      XmlAttributes YearAttributes = new XmlAttributes(); 

      PublisherAttributes.XmlElements.Add(new XmlElementAttribute("Publisher")); 
      YearAttributes.XmlElements.Add(new XmlElementAttribute("Year")); 

      overrides.Add(typeof(Book), "Publisher", PublisherAttributes); 
      overrides.Add(typeof(Book), "Year", YearAttributes); 

      XmlSerializer ser = new XmlSerializer(typeof(Book), overrides); 
      System.IO.TextReader oReader = new System.IO.StringReader(sXml); 

      Book oBook = (Book) ser.Deserialize(oReader); 

这是否帮助?

+0

感谢您的回复。使用覆盖将要求我知道要覆盖的成员的名称。你知道有什么通用的方法来达到这个目的吗?我已经更新了这个问题以包含使用场景。 – adentum

1

当你更新你的问题时,你需要将Type1转换为Type2的泛型逻辑。

低于溶液尝试,

对于这两种类型的类别(类型1类型2 &)我假定两个具有相同的名称相同的属性。

可以说我们有两本书Book & Book1。

public class Book 
{ 
    public string Title { get; set; } 

    [XmlAttribute()] 
    public string Publisher { get; set; } 

    [XmlAttribute()] 
    public string Year { get; set; } 
} 

public class Book1 
{ 
    public string Title { get; set; } 

    [XmlAttribute()] 
    public string Publisher { get; set; } 

    [XmlAttribute()] 
    public string Year { get; set; } 
} 

ConvertType1ToType2功能:

public static Type2 ConvertType1ToType2<Type1, Type2>(Type1 type1) 
    { 
     using (System.IO.MemoryStream objectStream = new System.IO.MemoryStream()) 
     { 
      XmlRootAttribute root = new XmlRootAttribute("Book"); 

      //Get All MemberInfo of Type1 
      Type objType1 = type1.GetType(); 
      System.Reflection.MemberInfo[] objType1Member = objType1.GetMembers(); 
      List<Type> extraTypesForType1 = new List<Type>(); 


      //Type1 => XmlAttributeOverrides 
      XmlAttributeOverrides Type1overrides = new XmlAttributeOverrides(); 
      foreach (System.Reflection.MemberInfo m in objType1Member) 
      { 
       if (m.MemberType.Equals(System.Reflection.MemberTypes.Property)) 
       { 
        XmlAttributes attributes = new XmlAttributes(); 
        attributes.XmlElements.Add(new XmlElementAttribute(m.Name)); 
        Type1overrides.Add(typeof(Type1), m.Name, attributes); 
        extraTypesForType1.Add(m.MemberType.GetType()); 
       } 

      } 

      XmlSerializer type1Serializer = new XmlSerializer(typeof(Type1), Type1overrides, extraTypesForType1.ToArray(),root,""); 

      //Type2 => XmlAttributeOverrides 
      Type objType2 = type1.GetType(); 
      System.Reflection.MemberInfo[] objType2Member = objType1.GetMembers(); 

      List<Type> extraTypesForType2 = new List<Type>(); 

      XmlAttributeOverrides Type2overrides = new XmlAttributeOverrides(); 
      foreach (System.Reflection.MemberInfo m in objType2Member) 
      { 
       if (m.MemberType.Equals(System.Reflection.MemberTypes.Property)) 
       { 
        XmlAttributes attributes = new XmlAttributes(); 
        attributes.XmlElements.Add(new XmlElementAttribute(m.Name)); 
        Type2overrides.Add(typeof(Type2), m.Name, attributes); 
        extraTypesForType2.Add(m.MemberType.GetType()); 
       } 

      } 

      XmlSerializer type2Deserializer = new XmlSerializer(typeof(Type2), Type2overrides, extraTypesForType2.ToArray(),root,""); 

      type1Serializer.Serialize(objectStream, type1); 
      objectStream.Position = 0; 

      Type2 t = (Type2)type2Deserializer.Deserialize(objectStream); 
      return t; 
     } 

现在创建Book类对象并调用函数ConvertType1ToType2。

Book book = new Book(); 
      book.Title = "Introduction to c#"; 
      book.Publisher = "John Smith"; 
      book.Year = "2012"; 

Book1 book1 = ConvertType1ToType2<Book, Book1>(book); 

希望这个解决方案可以工作。

+0

感谢您的方法。我想知道,因为我们使用反射,我想我们可以跳过序列化部分并直接设置对象? – adentum