.net 将对象序列化为文本文件:哪个API/框架?
我想将程序的DataModel对象保存到一个文件中,并能够再次重新加载相同的对象图。我希望它是某种风格的文本文件,所以我可以区分它并在文本编辑器中打开它。XML很好,而且似乎是一个很好的起点,因为.NET内置了XML序列化 但是我应该选择哪种风格的XML序列化呢?我知道(但现在已经被弃用了),(不错,但非常有限),和(我对这两个都不太了解)。(这只是来自微软的消息——好悲伤!) 我也对开源框架持开放态度,而且我不喜欢XML(看起来也很有趣) 我在序列化框架中的一些常规首选项:.net 将对象序列化为文本文件:哪个API/框架?,.net,serialization,.net,Serialization,我想将程序的DataModel对象保存到一个文件中,并能够再次重新加载相同的对象图。我希望它是某种风格的文本文件,所以我可以区分它并在文本编辑器中打开它。XML很好,而且似乎是一个很好的起点,因为.NET内置了XML序列化 但是我应该选择哪种风格的XML序列化呢?我知道(但现在已经被弃用了),(不错,但非常有限),和(我对这两个都不太了解)。(这只是来自微软的消息——好悲伤!) 我也对开源框架持开放态度,而且我不喜欢XML(看起来也很有趣) 我在序列化框架中的一些常规首选项: 我真的不必编写任
- 我真的不必编写任何代码(或XML配置文件)来获取要序列化的新添加属性。我可以(勉强)接受必须添加属性,但我的开销越小越好
- 约定优于配置
- 任何可以序列化循环对象图的东西都有额外的积分。如果必须的话,我可以避免这种情况,但我不想为了其他人的序列化框架的方便而让我的编码变得更难
- 我更喜欢保存属性值的东西,而不是直接进入私有字段
- 我想要一些可以在将来进行验证的东西。如果我重命名属性或枚举值,我不希望我的旧文件被删除;我需要某种方法来定义升级路径并重新映射加载时的值(最好不用编写大量的XML配置文件),并且我希望能够编写自动回归测试来证明我可以打开旧文件
- 如果它可以自动忽略对象的事件,而不需要为每个对象添加额外的属性,那就太好了。将事件写入文本格式是没有意义的
- 如果它能在Silverlight和成熟的.NET中工作,那将是非常酷的。(我短期内不需要这个,它会很酷的。)
但是,为了公平起见,我建议您阅读详细的比较。使用XmlSerializer或DataContractSerializer,除非他们不能满足您的要求。我打赌他们可以交付,而你将不需要其他任何东西。这是一个庞大的需求列表。就个人而言,我认为DataContractSerializer可以满足您的大多数需求 1) 您可以添加属性,它们将自动拾取(假设您有.NET3.5SP1) 2) 它有一些版本控制支持 3) 它存在于Silverlight中,尽管缺少了一些特性,比如PreserveObjectReferences(我想) 4) 您可以显式定义要序列化的内容,这样就可以排除私有字段,尽管如果您不指定任何内容,它们将被包括在内
5) 很确定它可以处理循环对象图,但不要引用我的话。我写了一些东西。。希望能帮助你
public class TAObjectSerializer
{
private static void __serializeData(object result, Type propType, XmlWriter wr)
{
if (result != null)
{
TypeConverter tc = TypeDescriptor.GetConverter(result);
if (tc != null && tc.CanConvertTo(typeof(string)) && tc.CanConvertFrom(typeof(string)))
{
wr.WriteString(tc.ConvertTo(result, typeof(string)) as string);
}
else if (propType.IsArray)
{
Array tmp = result as Array;
if (propType.GetElementType() == typeof(object))
{
for (int i = 0; i < tmp.Length; i++)
{
object v = tmp.GetValue(i);
wr.WriteStartElement("item");
if (v == null)
{
wr.WriteAttributeString("type", "");
}
else
{
Type vt = v.GetType();
wr.WriteAttributeString("type", (vt.IsPrimitive || v is string || v is decimal || v is DateTime || vt.IsArray) ? vt.ToString() : vt.AssemblyQualifiedName);
__serializeData(v, v.GetType(), wr);
}
wr.WriteEndElement();
}
}
else
{
for (int i = 0; i < tmp.Length; i++)
{
object v = tmp.GetValue(i);
wr.WriteStartElement("item");
if (v != null)
{
__serializeData(v, v.GetType(), wr);
}
wr.WriteEndElement();
}
}
}
else if (propType.IsSerializable)
{
using (MemoryStream __ = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(__, result);
wr.WriteString(Convert.ToBase64String(__.ToArray()));
}
}
else if (propType.IsClass)
{
wr.WriteRaw(__serialize(result));
}
}
}
private static void __serializeItem(object obj, PropertyInfo pi, XmlWriter wr)
{
Type propType = pi.PropertyType;
object result = pi.GetValue(obj, null);
wr.WriteStartElement("property");
wr.WriteAttributeString("type", (propType.IsPrimitive || result is string || result is decimal || result is DateTime || propType.IsArray) ? propType.ToString() : propType.AssemblyQualifiedName);
wr.WriteAttributeString("name", pi.Name);
__serializeData(result, propType, wr);
wr.WriteEndElement();
}
private static string __serialize(object obj)
{
StringBuilder sb = new StringBuilder();
XmlWriterSettings set = new XmlWriterSettings();
set.OmitXmlDeclaration = true;
using (XmlWriter wr = XmlWriter.Create(sb, set))
{
Type t = obj.GetType();
wr.WriteStartElement("object");
wr.WriteAttributeString("type", t.AssemblyQualifiedName);
if (t.IsClass && !(obj is string))
{
PropertyInfo[] list = t.GetProperties();
foreach (PropertyInfo pi in list)
{
if (pi.CanRead && pi.CanWrite && pi.GetCustomAttributes(typeof(NonSerializedAttribute), true).Length == 0)
{
__serializeItem(obj, pi, wr);
}
}
}
wr.WriteEndElement();
}
return sb.ToString();
}
public static XmlDocument Serialize(object obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
XmlDocument doc = new XmlDocument();
string str = __serialize(obj);
if (!string.IsNullOrEmpty(str))
doc.LoadXml(str);
return doc;
}
private static object __deserializeItem(Type propType, XmlNode node)
{
TypeConverter tc = TypeDescriptor.GetConverter(propType);
if (tc != null && tc.CanConvertTo(typeof(string)) && tc.CanConvertFrom(typeof(string)))
{
return tc.ConvertFrom(node.InnerText);
}
else if (propType.IsArray)
{
if (propType.GetElementType() == typeof(object))
{
XmlNodeList nl = node.SelectNodes("item");
Array tmp = Array.CreateInstance(typeof(object), nl.Count);
for (int i = 0; i < nl.Count; i++)
{
XmlNode p = nl[i];
Type _t = Type.GetType(p.Attributes["type"].Value);
if (_t == null)
tmp.SetValue(null, i);
else
tmp.SetValue(__deserializeItem(_t, p), i);
}
return tmp;
}
else
{
Type _t = propType.GetElementType();
XmlNodeList nl = node.SelectNodes("item");
Array tmp = Array.CreateInstance(_t, nl.Count);
for (int i = 0; i < nl.Count; i++)
{
XmlNode p = nl[i];
tmp.SetValue(__deserializeItem(_t, p), i);
}
return tmp;
}
}
else if (propType.IsSerializable)
{
using (MemoryStream __ = new MemoryStream(Convert.FromBase64String(node.InnerText)))
{
BinaryFormatter bf = new BinaryFormatter();
return bf.Deserialize(__);
}
}
else if (propType.IsClass)
{
return __deserialize(node);
}
return null;
}
private static object __deserialize(XmlNode t)
{
try
{
object tmp = Activator.CreateInstance(Type.GetType(t.Attributes["type"].Value));
XmlNodeList nl = t.SelectNodes("property");
Type objType = tmp.GetType();
foreach (XmlNode p in nl)
{
string name = p.Attributes["name"].Value;
PropertyInfo pi = objType.GetProperty(name);
Type propType = Type.GetType(p.Attributes["type"].Value);
if (propType == pi.PropertyType)
{
pi.SetValue(tmp, __deserializeItem(propType, p), null);
}
}
return tmp;
}
catch
{
}
return null;
}
public static object Deserialize(XmlDocument doc)
{
XmlNode nd = doc.SelectSingleNode("object");
if (nd == null)
throw new ArgumentOutOfRangeException();
return __deserialize(nd);
}
}
**
如果属性未标记为非序列化属性,则此类将序列化所有读写属性
祝你好运根据经验,我们发现XmlSerializer很烦人,因为它不允许序列化私有字段。这最终促使我们进行二进制序列化()。DataContractSerializer似乎已解决此问题。不过,我还没有尝试过。下面是一些关于其版本控制支持的好信息:数据契约版本控制,最佳实践:数据契约版本控制Joe White 26秒前看起来Silverlight one确实支持PreserveObjectReferences(这是获得循环对象图的方式)。有没有办法使其支持双向链接?
Usage :
Serialize : TAObjectSerializer.Serialize(myClassInstance); //this returns as XmlDocument
Deserialize : TAObjectSerializer.Deserialize(myXmlDocument); //this returns as object instance