.net 将对象序列化为文本文件:哪个API/框架?

.net 将对象序列化为文本文件:哪个API/框架?,.net,serialization,.net,Serialization,我想将程序的DataModel对象保存到一个文件中,并能够再次重新加载相同的对象图。我希望它是某种风格的文本文件,所以我可以区分它并在文本编辑器中打开它。XML很好,而且似乎是一个很好的起点,因为.NET内置了XML序列化 但是我应该选择哪种风格的XML序列化呢?我知道(但现在已经被弃用了),(不错,但非常有限),和(我对这两个都不太了解)。(这只是来自微软的消息——好悲伤!) 我也对开源框架持开放态度,而且我不喜欢XML(看起来也很有趣) 我在序列化框架中的一些常规首选项: 我真的不必编写任

我想将程序的DataModel对象保存到一个文件中,并能够再次重新加载相同的对象图。我希望它是某种风格的文本文件,所以我可以区分它并在文本编辑器中打开它。XML很好,而且似乎是一个很好的起点,因为.NET内置了XML序列化

但是我应该选择哪种风格的XML序列化呢?我知道(但现在已经被弃用了),(不错,但非常有限),和(我对这两个都不太了解)。(这只是来自微软的消息——好悲伤!)

我也对开源框架持开放态度,而且我不喜欢XML(看起来也很有趣)

我在序列化框架中的一些常规首选项:

  • 我真的不必编写任何代码(或XML配置文件)来获取要序列化的新添加属性。我可以(勉强)接受必须添加属性,但我的开销越小越好
  • 约定优于配置
  • 任何可以序列化循环对象图的东西都有额外的积分。如果必须的话,我可以避免这种情况,但我不想为了其他人的序列化框架的方便而让我的编码变得更难
  • 我更喜欢保存属性值的东西,而不是直接进入私有字段
  • 我想要一些可以在将来进行验证的东西。如果我重命名属性或枚举值,我不希望我的旧文件被删除;我需要某种方法来定义升级路径并重新映射加载时的值(最好不用编写大量的XML配置文件),并且我希望能够编写自动回归测试来证明我可以打开旧文件
  • 如果它可以自动忽略对象的事件,而不需要为每个对象添加额外的属性,那就太好了。将事件写入文本格式是没有意义的
  • 如果它能在Silverlight和成熟的.NET中工作,那将是非常酷的。(我短期内不需要这个,它会很酷的。)
建议?

我认为这是您最好的选择-它是.NET framework的一个更现代的序列化程序,并且工作得非常好


但是,为了公平起见,我建议您阅读详细的比较。

使用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