BaseContent.cs
public class BaseContent { // Some auto properties }
News.cs
public class News : BaseContent { // Some more auto properties }
Events.cs
public class Event : BaseContent { // Some more auto properites }
GenericResponse.cs
public class GenericResponse<T> { [XmlArray("Content")] [XmlArrayItem("NewsObject",typeof(News)] [XmlArrayItem("EventObject",typeof(Event)] public List<T> ContentItems { get; set; } }
NewsResponse.cs
public class NewsResponse : GenericResponse<News> {}
EventResponse.cs
public class EventResponse : GenericResponse<Event> {}
你可以看到,我有一个基类BaseContent和从它派生的两个类.接下来我有一个通用响应类,因为xml文件的结构总是相同的,但是在某些属性中它们有所不同.
我以为我可以用[XmlArrayItem]指定用于特定类的名称.但是现在我得到错误:
System.InvalidOperationException: Unable to generate a temporary class (result=1).
error CS0012: The type ‘System.Object’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Runtime,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a’.
我无法添加此引用,因为我正在使用Windows 8应用程序.
如果我注释掉其中一个[XmlArrayItem],它的工作效果很好.
任何人都有一个想法来解决这个问题?
更新
我不能使用DataContractSerializer,因为我必须使用XmlAttributes
解决方法
您没有提供对象的所有属性,所以允许我添加一些 – 就像一个例子:
public class BaseContent { [XmlAttribute("Name")] public string Name { get; set; } } [XmlType(TypeName = "EventObject")] public class Event : BaseContent { [XmlAttribute("EventId")] public int EventId { get; set; } } [XmlType(TypeName = "NewsObject")] public class News : BaseContent { [XmlAttribute("NewsId")] public int NewsId { get; set; } }
GenericResponse.cs可以这样定义 – 不需要为数组项指定typeof:
public class GenericResponse<T> { [XmlArray("Content")] public List<T> ContentItems { get; set; } public GenericResponse() { this.ContentItems = new List<T>(); } }
然后你有响应类:
public class EventResponse : GenericResponse<Event> { } public class NewsResponse : GenericResponse<News> { }
示例1:序列化EventResponse对象
var response = new EventResponse { ContentItems = new List<Event> { new Event { EventId = 1,Name = "Event 1" },new Event { EventId = 2,Name = "Event 2" } } }; string xml = XmlSerializer<EventResponse>.Serialize(response);
输出XML:
<?xml version="1.0" encoding="utf-8"?> <EventResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Content> <EventObject Name="Event 1" EventId="1" /> <EventObject Name="Event 2" EventId="2" /> </Content> </EventResponse>
如果您尝试与NewsResponse相同,它将正常工作. BTW我使用我的generic XmlSerializer,点击链接了解更多.
XmlSerializer.cs:
/// <summary> /// XML serializer helper class. Serializes and deserializes objects from/to XML /// </summary> /// <typeparam name="T">The type of the object to serialize/deserialize. /// Must have a parameterless constructor and implement <see cref="Serializable"/></typeparam> public class XmlSerializer<T> where T: class,new() { /// <summary> /// Deserializes a XML string into an object /// Default encoding: <c>UTF8</c> /// </summary> /// <param name="xml">The XML string to deserialize</param> /// <returns>An object of type <c>T</c></returns> public static T Deserialize(string xml) { return Deserialize(xml,Encoding.UTF8,null); } /// <summary> /// Deserializes a XML string into an object /// Default encoding: <c>UTF8</c> /// </summary> /// <param name="xml">The XML string to deserialize</param> /// <param name="encoding">The encoding</param> /// <returns>An object of type <c>T</c></returns> public static T Deserialize(string xml,Encoding encoding) { return Deserialize(xml,encoding,null); } /// <summary> /// Deserializes a XML string into an object /// </summary> /// <param name="xml">The XML string to deserialize</param> /// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlReaderSettings"/></param> /// <returns>An object of type <c>T</c></returns> public static T Deserialize(string xml,XmlReaderSettings settings) { return Deserialize(xml,settings); } /// <summary> /// Deserializes a XML string into an object /// </summary> /// <param name="xml">The XML string to deserialize</param> /// <param name="encoding">The encoding</param> /// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlReaderSettings"/></param> /// <returns>An object of type <c>T</c></returns> public static T Deserialize(string xml,Encoding encoding,XmlReaderSettings settings) { if (string.IsNullOrEmpty(xml)) throw new ArgumentException("XML cannot be null or empty","xml"); XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); using (MemoryStream memoryStream = new MemoryStream(encoding.GetBytes(xml))) { using (XmlReader xmlReader = XmlReader.Create(memoryStream,settings)) { return (T) xmlSerializer.Deserialize(xmlReader); } } } /// <summary> /// Deserializes a XML file. /// </summary> /// <param name="filename">The filename of the XML file to deserialize</param> /// <returns>An object of type <c>T</c></returns> public static T DeserializeFromFile(string filename) { return DeserializeFromFile(filename,new XmlReaderSettings()); } /// <summary> /// Deserializes a XML file. /// </summary> /// <param name="filename">The filename of the XML file to deserialize</param> /// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlReaderSettings"/></param> /// <returns>An object of type <c>T</c></returns> public static T DeserializeFromFile(string filename,XmlReaderSettings settings) { if (string.IsNullOrEmpty(filename)) throw new ArgumentException("filename","XML filename cannot be null or empty"); if (! File.Exists(filename)) throw new FileNotFoundException("Cannot find XML file to deserialize",filename); // Create the stream writer with the specified encoding using (XmlReader reader = XmlReader.Create(filename,settings)) { System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(T)); return (T) xmlSerializer.Deserialize(reader); } } /// <summary> /// Serialize an object /// </summary> /// <param name="source">The object to serialize</param> /// <returns>A XML string that represents the object to be serialized</returns> public static string Serialize(T source) { // indented XML by default return Serialize(source,null,GetIndentedSettings()); } /// <summary> /// Serialize an object /// </summary> /// <param name="source">The object to serialize</param> /// <param name="namespaces">Namespaces to include in serialization</param> /// <returns>A XML string that represents the object to be serialized</returns> public static string Serialize(T source,XmlSerializerNamespaces namespaces) { // indented XML by default return Serialize(source,namespaces,GetIndentedSettings()); } /// <summary> /// Serialize an object /// </summary> /// <param name="source">The object to serialize</param> /// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlWriterSettings"/></param> /// <returns>A XML string that represents the object to be serialized</returns> public static string Serialize(T source,XmlWriterSettings settings) { return Serialize(source,settings); } /// <summary> /// Serialize an object /// </summary> /// <param name="source">The object to serialize</param> /// <param name="namespaces">Namespaces to include in serialization</param> /// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlWriterSettings"/></param> /// <returns>A XML string that represents the object to be serialized</returns> public static string Serialize(T source,XmlSerializerNamespaces namespaces,XmlWriterSettings settings) { if (source == null) throw new ArgumentNullException("source","Object to serialize cannot be null"); string xml = null; XmlSerializer serializer = new XmlSerializer(source.GetType()); using (MemoryStream memoryStream = new MemoryStream()) { using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream,settings)) { System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(T)); x.Serialize(xmlWriter,source,namespaces); memoryStream.Position = 0; // rewind the stream before reading back. using (StreamReader sr = new StreamReader(memoryStream)) { xml = sr.ReadToEnd(); } } } return xml; } /// <summary> /// Serialize an object to a XML file /// </summary> /// <param name="source">The object to serialize</param> /// <param name="filename">The file to generate</param> public static void SerializeToFile(T source,string filename) { // indented XML by default SerializeToFile(source,filename,GetIndentedSettings()); } /// <summary> /// Serialize an object to a XML file /// </summary> /// <param name="source">The object to serialize</param> /// <param name="filename">The file to generate</param> /// <param name="namespaces">Namespaces to include in serialization</param> public static void SerializeToFile(T source,string filename,XmlSerializerNamespaces namespaces) { // indented XML by default SerializeToFile(source,GetIndentedSettings()); } /// <summary> /// Serialize an object to a XML file /// </summary> /// <param name="source">The object to serialize</param> /// <param name="filename">The file to generate</param> /// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlWriterSettings"/></param> public static void SerializeToFile(T source,XmlWriterSettings settings) { SerializeToFile(source,settings); } /// <summary> /// Serialize an object to a XML file /// </summary> /// <param name="source">The object to serialize</param> /// <param name="filename">The file to generate</param> /// <param name="namespaces">Namespaces to include in serialization</param> /// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlWriterSettings"/></param> public static void SerializeToFile(T source,"Object to serialize cannot be null"); XmlSerializer serializer = new XmlSerializer(source.GetType()); using (XmlWriter xmlWriter = XmlWriter.Create(filename,settings)) { System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(T)); x.Serialize(xmlWriter,namespaces); } } #region Private methods private static XmlWriterSettings GetIndentedSettings() { XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); xmlWriterSettings.Indent = true; xmlWriterSettings.IndentChars = "\t"; return xmlWriterSettings; } #endregion }