如何将派生类序列化为其基类

时间:2009-12-01 05:06:13

标签: .net serialization

我有一个派生类,只向基类添加方法。如何序列化派生类以使其与基类的序列化相匹配? 即派生类的序列化xml应如下所示:

<BaseClass>
  ...
</BaseClass>

e.g。 以下将抛出InvalidOperationException “不期望DerivedClass类型。使用XmlInclude或SoapInclude属性指定静态未知的类型。”

Class BaseClass {}

Class DerivedClass : BaseClass {}

DerivedClass derived = new DerivedClass();

StreamWriter stream = new StreamWriter("output file path");
XmlSerializer serializer = new XmlSerializer(GetType(BaseClass));
serializer(stream, derived);

5 个答案:

答案 0 :(得分:4)

您必须将GetType(DerivedClass)传递给序列化器构造函数,它必须与您序列化的对象的类型相匹配。您可以使用<XmlRoot>属性重命名为根元素。此示例代码按预期工作:

using System;
using System.Xml.Serialization;
using System.IO;

class Program {
  static void Main(string[] args) {
    var obj = new DerivedClass();
    obj.Prop = 42;
    var xs = new XmlSerializer(typeof(DerivedClass));
    var sw = new StringWriter();
    xs.Serialize(sw, obj);
    Console.WriteLine(sw.ToString());

    var sr = new StringReader(sw.ToString());
    var obj2 = (BaseClass)xs.Deserialize(sr);
    Console.ReadLine();
  }
}

public class BaseClass {
  public int Prop { get; set; }
}
[XmlRoot("BaseClass")]
public class DerivedClass : BaseClass { }

答案 1 :(得分:1)

您还可以为BaseClass实现ICloneable接口,然后执行:

var sw = new StringWriter()

var base = (derived as BaseClass).Clone()
var serializer = new XmlSerializer(typeof(BaseClass))
serializer.Serialize(sw, base)

Console.WriteLine(sw.ToString())

不是一个完美的approche,但如果你的基类很简单,那么它也应该有效。

答案 2 :(得分:0)

我还没有尝试过,但你能不能投它吗?

serializer(stream, (BaseClass)derived);

修改

另外,如果你想拥有一个可以处理多个派生类的单个XmlSerialiser&amp;然后,您需要在XmlSerialiser构造函数中指定所有类型。

  XmlSerializer serializer = new XmlSerializer(typeof(BaseClass), new Type[] {typeof(DerivedClass)});

然后它会愉快地序列化多种类型。但是,您还必须使用上面提到的解决方案来获取输出xml以匹配类。

答案 3 :(得分:0)

经过一段谷歌搜索后;)我可以说你需要更多的代码并为你的基类实现IXmlSerializable,将所有接口方法声明为虚拟,并在派生类上覆盖它们。以下是通过提及的界面解析的示例topicsimilar problem

答案 4 :(得分:0)

提供的答案要求更改原始基类以提供适当的名称。我觉得这是没有经验的,将演示一种在任何类上提供结果的方法,只要无需更改源代码


通过提供对通用类型的扩展方法,可以根据需要为任何类型提供此解决方案。

public static class SerializerExtensions
{
    public static string ToBaseNamedXml<T>(this T instance)
    {    
        var root = instance.GetType().BaseType.UnderlyingSystemType.Name; // Get base name.

        var jsr = JsonConvert.SerializeObject( instance );               // Into JSON

        var xDoc = JsonConvert.DeserializeXmlNode(jsr, root);            // Provide base name

        return xDoc.OuterXml;                                            // Out to string
    }
}

上面的代码使用Newtonsoft JSON序列化程序的nuget包序列化为JSON,该JSON获取派生的所有属性,但不派生的名称,像这样{"dProp":90125,"Prop":42}。然后,我们再次使用JSON逆转该过程,但提供派生对象的根名称​​ 。最后,我们将XDocument的外部xml作为字符串返回。

结果 <BaseClass><dProp>90125</dProp><Prop>42</Prop></BaseClass>


测试类注意,我在测试派生类中添加了一个名为dProp

的新属性。
public class BaseClass { public int Prop { get; set; } }

public class DerivedClass : BaseClass { public int dProp { get; set; } }

测试使用情况

var dc = new DerivedClass() { Prop = 42, dProp = 90125} ;

var xmlStringResult = dc.ToBaseNamedXml();