我有一个派生类,只向基类添加方法。如何序列化派生类以使其与基类的序列化相匹配? 即派生类的序列化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);
答案 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
,将所有接口方法声明为虚拟,并在派生类上覆盖它们。以下是通过提及的界面解析的示例topic和similar 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();