在c#中使用多重专门化/继承反序列化XML文档

本文关键字:继承 反序列化 XML 文档 专门化 | 更新日期: 2023-09-27 18:06:12

我有一个XML文档,其中有几个专门化的条目,我设法从这里得到一个解决方案来反序列化它。我已经做了完全相同的例子,并作为一个魅力,但它只工作,如果一个专门的类出现。在链接示例中(如上所示),假设有另一个专门来自Instrument的类(例如,Drums)。如何使用此方法告诉反序列化人员何时转换到每个专门化类?

序列化对象:

public class Orchestra
{
   public Instrument[] Instruments;
}   
public class Instrument
{
   public string Name;
}
public class Brass:Instrument
{
   public bool IsValved;
}

反序列化示例:

 public void DeserializeObject(string filename)
   {
      XmlAttributeOverrides attrOverrides = 
         new XmlAttributeOverrides();
      XmlAttributes attrs = new XmlAttributes();
      // Create an XmlElementAttribute to override the Instrument.
      XmlElementAttribute attr = new XmlElementAttribute();
      attr.ElementName = "Brass";
      attr.Type = typeof(Brass);
      // Add the XmlElementAttribute to the collection of objects.
      attrs.XmlElements.Add(attr);
      attrOverrides.Add(typeof(Orchestra), "Instruments", attrs);
      // Create the XmlSerializer using the XmlAttributeOverrides.
      XmlSerializer s = 
      new XmlSerializer(typeof(Orchestra), attrOverrides);
      FileStream fs = new FileStream(filename, FileMode.Open);
      Orchestra band = (Orchestra) s.Deserialize(fs);
      Console.WriteLine("Brass:");
      /* The difference between deserializing the overridden 
      XML document and serializing it is this: To read the derived 
      object values, you must declare an object of the derived type 
      (Brass), and cast the Instrument instance to it. */
      Brass b;
      foreach(Instrument i in band.Instruments) 
      {
         b = (Brass)i;
         Console.WriteLine(
         b.Name + "'n" + 
         b.IsValved);
      }
   }

我试过添加另一个属性覆盖,但它不起作用,我也试过制作两个单独的反序列化器(每个都有一个属性覆盖,我想转换为对象),它既不工作,因为它不能转换其他类型的对象,导致类型异常。

任何想法?

在c#中使用多重专门化/继承反序列化XML文档

如果您可以控制.cs文件,您可以像这样直接将属性添加到主类中,可以使用属性完全控制序列化,在极端情况下,您可以实现IXmlSerializable接口。

我在这里写了一个简单的例子,但你应该提供一个例子,说明它不适合你的地方,以及你得到的异常,以便看到你的具体问题。在序列化和反序列化过程中有许多事情可能会失败,异常将告诉您原因。例如,如果类不是公共的,它将抛出异常。

public class Program
{
    public class Orchestra
    {
        public Instrument[] Instruments {get; set;}
    }
    [XmlInclude(typeof(Brass))]
    [XmlInclude(typeof(Guitar))]
    public class Instrument
    {
        public string Name { get; set; }
        [XmlIgnore]
        public string DoNotSerialize { get; set; }
    }
    public class Brass : Instrument
    {
        public bool IsValved { get; set; }
        public override string ToString()
        {
            return string.Format("This is a{0} Brass.",IsValved?" valved":"n unvalved");
        }
    }
    public class Guitar: Instrument
    {
        public int Strings { get; set; }
        public override string ToString()
        {
            return String.Format("This is a {0} string Guitar.", Strings);
        }
    }
    static XmlSerializer s;
    static void Main(string[] args)
    {
        s = new XmlSerializer(typeof(Orchestra));
        serialize("%temp%test.xml");
        deserialize("%temp%test.xml");
        Console.ReadLine();
    }
    static void serialize(string filename)
    {
        Orchestra o = new Orchestra();
        o.Instruments = new Instrument[]
        {
            new Brass
            {
                IsValved=true
            },
            new Brass {IsValved=false },
            new Guitar {Strings=12 }
        };
        using (FileStream fs = new FileStream(filename, FileMode.Create))
        {
            s.Serialize(fs, o);
        }
    }
    static void deserialize(string filename)
    {
        Orchestra band;
        using (FileStream fs = new FileStream(filename, FileMode.Open))
        {
            band = (Orchestra)s.Deserialize(fs);
        }
        foreach (Instrument i in band.Instruments)
        {
            Console.WriteLine("{0}: {1}", i.GetType(), i.ToString());
        }
    }
}