栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

XML序列化和继承的类型

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

XML序列化和继承的类型

问题解决了!

好的,所以我终于到达了那里(诚然,这里有
很多 帮助!)。

总结一下:

目标:

  • 由于维护麻烦,我不想 沿用XmlInclude 路线。
  • 找到解决方案后,我希望它能够在其他应用程序中快速实现。
  • 可以使用Abstract类型的集合以及各个抽象属性。
  • 我真的不想打扰在具体的类中做“特殊”的事情。

确定的问题/要点:

  • XmlSerializer进行了 一些很酷的反映,但是在涉及抽象类型时,它是 非常 有限的(即,它仅适用于抽象类型本身的实例,而不适用于子类)。
  • Xml属性装饰器定义XmlSerializer如何处理其发现的属性。也可以指定物理类型,但这会在类和序列化程序之间建立 紧密的耦合 (不好)。
  • 我们可以通过创建实现 IXmlSerializable 的类来实现自己的XmlSerializer 。

解决方案

我创建了一个通用类,在其中您将通用类型指定为将要使用的抽象类型。这使该类能够在抽象类型和具体类型之间“转换”,因为我们可以对转换进行硬编码(即,与XmlSerializer相比,我们可以获得更多的信息)。

然后,我实现了 IXmlSerializable
接口,这非常简单,但是在序列化时,我们需要确保将具体类的类型写入XML,以便在反序列化时可以将其返回。同样重要的是要注意它必须 完全合格
,因为这两个类所在的程序集可能会有所不同。当然,这里需要进行一些类型检查和操作。

由于XmlSerializer无法转换,因此我们需要提供代码来执行此操作,因此隐式运算符将被重载(我什至不知道您可以做到这一点!)。

AbstractXmlSerializer的代码是这样的:

using System;using System.Collections.Generic;using System.Text;using System.Xml.Serialization;namespace Utility.Xml{    public class AbstractXmlSerializer<AbstractType> : IXmlSerializable    {        // Override the Implicit Conversions Since the XmlSerializer        // Casts to/from the required types implicitly.        public static implicit operator AbstractType(AbstractXmlSerializer<AbstractType> o)        { return o.Data;        }        public static implicit operator AbstractXmlSerializer<AbstractType>(AbstractType o)        { return o == null ? null : new AbstractXmlSerializer<AbstractType>(o);        }        private AbstractType _data;        /// <summary>        /// [Concrete] Data to be stored/is stored as XML.        /// </summary>        public AbstractType Data        { get { return _data; } set { _data = value; }        }        /// <summary>        /// **DO NOT USE** This is only added to enable XML Serialization.        /// </summary>        /// <remarks>DO NOT USE THIS CONSTRUCTOR</remarks>        public AbstractXmlSerializer()        { // Default Ctor (Required for Xml Serialization - DO NOT USE)        }        /// <summary>        /// Initialises the Serializer to work with the given data.        /// </summary>        /// <param name="data">Concrete Object of the AbstractType Specified.</param>        public AbstractXmlSerializer(AbstractType data)        { _data = data;        }        #region IXmlSerializable Members        public System.Xml.Schema.XmlSchema GetSchema()        { return null; // this is fine as schema is unknown.        }        public void ReadXml(System.Xml.XmlReader reader)        { // Cast the Data back from the Abstract Type. string typeAttrib = reader.GetAttribute("type"); // Ensure the Type was Specified if (typeAttrib == null)     throw new ArgumentNullException("Unable to Read Xml Data for Abstract Type '" + typeof(AbstractType).Name +         "' because no 'type' attribute was specified in the XML."); Type type = Type.GetType(typeAttrib); // Check the Type is Found. if (type == null)     throw new InvalidCastException("Unable to Read Xml Data for Abstract Type '" + typeof(AbstractType).Name +         "' because the type specified in the XML was not found."); // Check the Type is a Subclass of the AbstractType. if (!type.IsSubclassOf(typeof(AbstractType)))     throw new InvalidCastException("Unable to Read Xml Data for Abstract Type '" + typeof(AbstractType).Name +         "' because the Type specified in the XML differs ('" + type.Name + "')."); // Read the Data, Deserializing based on the (now known) concrete type. reader.ReadStartElement(); this.Data = (AbstractType)new     XmlSerializer(type).Deserialize(reader); reader.ReadEndElement();        }        public void WriteXml(System.Xml.XmlWriter writer)        { // Write the Type Name to the XML Element as an Attrib and Serialize Type type = _data.GetType(); // BugFix: Assembly must be FQN since Types can/are external to current. writer.WriteAttributeString("type", type.AssemblyQualifiedName); new XmlSerializer(type).Serialize(writer, _data);        }        #endregion    }}

因此,从那里,我们如何告诉XmlSerializer使用我们的序列化程序而不是默认序列化程序?我们必须在Xml属性type属性中传递我们的类型,例如:

[XmlRoot("ClassWithAbstractCollection")]public class ClassWithAbstractCollection{    private List<AbstractType> _list;    [XmlArray("ListItems")]    [XmlArrayItem("ListItem", Type = typeof(AbstractXmlSerializer<AbstractType>))]    public List<AbstractType> List    {        get { return _list; }        set { _list = value; }    }    private AbstractType _prop;    [XmlElement("MyProperty", Type=typeof(AbstractXmlSerializer<AbstractType>))]    public AbstractType MyProperty    {        get { return _prop; }        set { _prop = value; }    }    public ClassWithAbstractCollection()    {        _list = new List<AbstractType>();    }}

在这里,您可以看到,我们有一个集合和一个单独的属性,我们要做的就是将名为parameter 的 类型 添加到Xml声明中,简单!:D

注意:如果您使用此代码,我将不胜感激。 它还将帮助吸引更多的人进入社区:)

现在,但是不确定在这里如何处理答案,因为他们都有自己的优点和缺点。我会升级那些我认为有用的代码(对那些没有用的代码没有任何冒犯),并在获得代表之后将其关闭:)

有趣的问题,很好解决的乐趣!:)



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/465521.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号