首页 新闻 会员 周边

c# 序列化

0
悬赏园豆:5 [已解决问题] 解决于 2012-02-09 10:01

在使用C# XmlSerializer 的时候,我想序列化的时候使用子类类型,反序列化的时候使用父类类型,是否有什么好的办法

c#
zxding1986的主页 zxding1986 | 初学一级 | 园豆:192
提问于:2012-02-08 17:49
< >
分享
最佳答案
0
#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
}
}

已测试过 可行。不过比较麻烦,要继承接口,还要在子类中重写。

收获园豆:5
waninlezu | 小虾三级 |园豆:661 | 2012-02-08 23:29
其他回答(2)
0

以下代码没有经过测试不过应该是可行的:

XmlSerializer serializer = new XmlSerializer(typeof(Derived));
//invoke serializer.Serialize
XmlSerializer deserializer = new XmlSerializer(typeof(Base));
//invoke deserializer.Deserialize

序列化时type参数用子类的类型,反序列化时type参数用父类类型(有两个XmlSerializer对象)。不过你这个需求还是真是奇怪,为什么反序列化要用父类类型?你就反序列化成子类类型,赋值给父类类型的变量不就行了。

水牛刀刀 | 园豆:6350 (大侠五级) | 2012-02-08 18:03

我原来具体需求是这样的,一个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 去反序列化应该是不行的
支持(0) 反对(0) zxding1986 | 园豆:192 (初学一级) | 2012-02-08 18:58

也感觉比较奇怪。。。

支持(0) 反对(0) 顾晓北 | 园豆:10844 (专家六级) | 2012-02-09 09:54
0

既然你自己已经知道要反序列的文件格式是子类(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;

甘南 | 园豆:271 (菜鸟二级) | 2012-02-09 09:42

我现在采用类似甘南方法,避开XMLSerializer,直接使用二进制,不过 waninlezu 很强大,感谢各位,结贴

支持(0) 反对(0) zxding1986 | 园豆:192 (初学一级) | 2012-02-09 10:00
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册