C# · 12月 27, 2021

c# – 使用不同类的通用列表XML序列化

我有以下代码:

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

解决方法 编辑:随意下载 demo project

您没有提供对象的所有属性,所以允许我添加一些 – 就像一个例子:

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}