在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);
}
}
我试过添加另一个属性覆盖,但它不起作用,我也试过制作两个单独的反序列化器(每个都有一个属性覆盖,我想转换为对象),它既不工作,因为它不能转换其他类型的对象,导致类型异常。
任何想法?
如果您可以控制.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());
}
}
}