在使用C# XmlSerializer 的时候,我想序列化的时候使用子类类型,反序列化的时候使用父类类型,是否有什么好的办法
#region
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
#endregion
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
var vip = new VipUser()
{
UserName = "fuck",
VipId = "123456"
};
var xml = XmlSerializer<VipUser>.Serialize(vip);
var user = XmlSerializer<User>.Deserialize(xml);
}
}
public class User : IXmlSerializable
{
public string UserName;
#region IXmlSerializable Members
public XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public virtual void ReadXml(XmlReader reader)
{
reader.Read();
reader.Read();
UserName = reader.Value;
// reader.ReadStartElement("user-name");
// reader.ReadEndElement();
}
public virtual void WriteXml(XmlWriter writer)
{
throw new NotImplementedException();
}
#endregion
}
[XmlRoot("User")]
public class VipUser : User
{
public string VipId;
public override void ReadXml(XmlReader reader)
{
throw new NotImplementedException();
}
public override void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("user-name");
writer.WriteString(UserName);
writer.WriteEndElement();
writer.WriteStartElement("vip-id");
writer.WriteString(VipId);
writer.WriteEndElement();
}
}
}
#region
using System.IO;
using System.Text;
using System.Xml.Serialization;
#endregion
namespace ConsoleApplication1
{
///<summary>
/// xml 序列化器
///</summary>
///<typeparam name = "T"></typeparam>
public class XmlSerializer<T>
{
private static readonly XmlSerializer _xmlSerializer = new XmlSerializer(typeof (T));
///<summary>
/// 序列化
///</summary>
///<param name = "obj"></param>
///<returns></returns>
public static string Serialize(T obj)
{
using (var writer = new Utf8Writer())
{
_xmlSerializer.Serialize(writer, obj);
return writer.ToString();
}
}
///<summary>
/// 反序列化
///</summary>
///<param name = "input"></param>
///<returns></returns>
public static T Deserialize(string input)
{
return (T) _xmlSerializer.Deserialize(new StringReader(input));
}
#region Nested type: Utf8Writer
private sealed class Utf8Writer : StringWriter
{
public override Encoding Encoding
{
get { return Encoding.UTF8; }
}
}
#endregion
}
}
已测试过 可行。不过比较麻烦,要继承接口,还要在子类中重写。
以下代码没有经过测试不过应该是可行的:
XmlSerializer serializer = new XmlSerializer(typeof(Derived));
//invoke serializer.Serialize
XmlSerializer deserializer = new XmlSerializer(typeof(Base));
//invoke deserializer.Deserialize
序列化时type参数用子类的类型,反序列化时type参数用父类类型(有两个XmlSerializer对象)。不过你这个需求还是真是奇怪,为什么反序列化要用父类类型?你就反序列化成子类类型,赋值给父类类型的变量不就行了。
我原来具体需求是这样的,一个key 和一个 序列化好的对象作为一条记录存进数据库
public abstract class TaskScheduleBase
public class DailySchedule:TaskScheduleBase
public class MothlySchedule:TaskScheduleBase
...
存的时候可以通过
Save<DailySchedule>(key,dailyScheduleEntity)
{
XmlSerializer serializer = new XmlSerializer(typeof(DailySchedule))
////Save to DB
...
}
但是取的时候 Get<T> (key) 这个T 我是无法决定的。
还有你提供的方法我试过了,当
XmlSerializer deserializer = new XmlSerializer(typeof(Base));
deserializer.Deserialize()
的时候 会有个 XMLDocument 错误 因为很多子类属性生成的XML标签 试图用父类的XMLSerializer 去反序列化应该是不行的
也感觉比较奇怪。。。
既然你自己已经知道要反序列的文件格式是子类(ChildClass),可以在反序列时后强行转化成父类(ParentClass)
下面是示例代码,你需要改成你的类型
FileStream fileStream = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
BinaryFormatter b = new BinaryFormatter();
ChildClass child = b.Deserialize(fileStream) as ChildClass ;
fileStream.Close();
ParentClass parent = (ParentClass )child;
我现在采用类似甘南方法,避开XMLSerializer,直接使用二进制,不过 waninlezu 很强大,感谢各位,结贴