我想将程序的DataModel对象保存到文件中,并且能够再次重新加载相同的对象图。我希望它在某种文本文件中,所以我可以将它区分开并在文本编辑器中打开它。 XML很好,而且似乎是一个很好的起点,因为.NET内置了XML序列化。
但我应该选择哪种XML序列化?我知道SoapFormatter(但现在已经弃用了),XamlWriter(很好但非常有限),XmlSerializer和DataContractSerializer(我对此都知之甚少)。 (而这只是来自微软的那些 - 好悲伤!)
我也对开源框架持开放态度,而且我不依赖于XML(JavaScriptSerializer看起来也很有趣。)
序列化框架中的一些常规偏好:
建议?
答案 0 :(得分:1)
我认为DataContractSerializer
是你最好的选择 - 它是一个更加现代的.NET框架序列化程序并且运行良好。
但是,为了公平起见,我建议您阅读XmlSerializer vs DataContractSerializer: Serialization in Wcf进行详细比较。
答案 1 :(得分:1)
使用XmlSerializer或DataContractSerializer,除非他们无法满足您的要求。我打赌他们可以提供,你不需要别的。
答案 2 :(得分:1)
这是一个很重要的要求清单。就个人而言,我认为DataContractSerializer可以满足您的大部分需求。
1)您可以添加属性,它们将自动被选中(假设您有.Net 3.5 SP1)
2)它有一些版本控制支持
3)它存在于Silverlight中,虽然缺少一些功能,如PreserveObjectReferences(我认为)
4)您可以明确定义要序列化的内容,这样您就可以排除私有字段,但如果您没有指定任何内容,它们将被包含在内。
5)很确定它处理循环对象图,但不要引用我。
答案 3 :(得分:0)
我写了......希望能帮到你..
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);
}
}
**
Usage :
Serialize : TAObjectSerializer.Serialize(myClassInstance); //this returns as XmlDocument
Deserialize : TAObjectSerializer.Deserialize(myXmlDocument); //this returns as object instance
**
如果属性未标记为 NonSerializedAttribute 属性
,则此类将序列化所有READ_WRITE属性祝你好运!