【问题标题】:IXmlSerializable and inheritanceIXmlSerializable 和继承
【发布时间】:2011-05-18 21:28:10
【问题描述】:

假设我有两个类,一个基类和一个派生类。它们是相当简单的类,主要只是充当数据结构(派生类显然稍微复杂一些)。

public class BaseUserSession
{
    // ... Various properties ...
}

public class DerivedUserSession : BaseUserSession
{
    // ... Even more properties ...
}

这些类需要序列化为 XML。现在,这可以通过在类声明上方指定[Serializable] 来完成,并且默认的 XML 序列化器运行良好。

然而,实际上,有多个类继承自基类。我的目标是能够让任何派生类的序列化 XML 可由基类使用。

我尝试了两种方法,目前都没有。首先,使用本机 XML 序列化程序和基类中的一些控件属性。生成的 XML 如下所示:

<?xml version="1.0" encoding="utf-16"?>
<DerivedUserSession xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SSO="www.mywebsite.com">
    <SSO:Id />
    <SSO:Authenticated>false</SSO:Authenticated>
    <SSO:Role />
    <EmailAddress />
    <FullName />
    <Street />
    <City />
    <State />
    <Zip />
    <DayPhone />
    <EveningPhone />
    <ErrorMessage />
    <Birthdate>0001-01-01T00:00:00</Birthdate>
    <CurrentControl>0</CurrentControl>
</DerivedUserSession>

SSO 为前缀的标签是从基类继承的标签。但是当我尝试将其反序列化为 BaseUserSession 对象时,它会引发异常:System.InvalidOperationException: &lt;DerivedUserSession xmlns=''&gt; was not expected.

我还尝试创建基类IXmlSerializable,并手动读取和写入所有 XML。但是,派生类无法写出它们的属性,我真的不想为每个类都实现IXmlSerializable

有更简单的方法吗?

=编辑=

我终于实现了一个相当丑陋的方法来完成这个。这两个类继承自基类,它们都实现了IXmlSerializable。每个类(包括基类)都使用反射将其字段值(煞费苦心地……)写入其自己的 XML 层次结构,并读回这些值。写入的第一个值始终来自基类。

每个应用程序还包含管理序列化到 XML 和返回的代码,提供简单的界面。会话本身现在除了简单地接受序列化的 XML 并将其存储在一个公共密钥下之外,什么也不做。进出 XML 的序列化都由应用程序处理,所有应用程序都使用公共的XmlRootAttribute 来绕过InvalidOperationException

所以现在,当另一个应用程序尝试反序列化最初在不同应用程序中创建的 XML 时,它会设法在遇到无法识别的元素之前读取公共基类值,然后在其他地方获取所需的值,这是可能的,因为它已经具有共同的基值。

我需要阅读序列化原则...

【问题讨论】:

    标签: c# xml serialization


    【解决方案1】:

    XmlSerialization 不是多态的(但是,成员属性与声明类一起使用;即,除非您使用 new 关键字(与 override 相比)否决成员,否则您将“继承”序列化属性。

    反序列化总是产生被序列化的实际类型。这很有意义,真的。

    【讨论】:

    • +1。 “XmlSerialization 不是多态的。”很好的总结了这件事。在放弃“自动化”(基于属性的)XML 序列化之前,我经历了与 OP 相同的故事。这是一个解决方法的世界。
    • @harpo:尽管说起来让我很痛苦,但我犹豫地同意了。序列化通用成员集合(例如,ICollection&lt;MyClass&gt; 或更糟,多态元素值的字典......)从未变得“容易”。
    【解决方案2】:

    好吧,我已经设法使用 DataContractSerializer 完成了您想做的事情。

    您应该将 KnownTypes 属性放在要序列化的基类上,或者更好的是,使用 DataContractResolver 来查找派生类型。

    我在网上看到了一个通用的实现,如果我再找到它,我会在这里发布。

    编辑

    找到它here

    如果您需要更多帮助,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-07
      • 2015-12-09
      • 1970-01-01
      • 1970-01-01
      • 2013-12-12
      • 2020-06-19
      相关资源
      最近更新 更多