如何从文件流中获取属性数

时间:2017-07-06 09:55:29

标签: c# serialization

我将特定对象保存在外部文件中,如下所示:

 public void SaveSettings(string SavedFilePath, object Class)
        {

            //open the stream to write the new file
            using (Stream StreamFile = File.Open(SavedFilePath, FileMode.CreateNew))
            {
                //instantiate the binary formatter object
                BinaryFormatter binformat = new BinaryFormatter();

                //loop through all properties in input object
                foreach (PropertyInfo prop in Class.GetType().GetProperties())
                {
                    //if the property is serailizable then serialize it and write its name and value in external file
                    if (prop.PropertyType.IsSerializable)
                        binformat.Serialize(StreamFile, prop.GetValue(Class, null));

                }

                //close the stream
                StreamFile.Close();
            }
        }

然后我像这样加载相同的对象:

 public void LoadSettings(string ConfigFile, object Class)
        {
            //open the stream to read the file
            using (Stream StreamFile = File.Open(ConfigFile, FileMode.Open))
            {
                //instantiate the binary formatter object
                BinaryFormatter binformat = new BinaryFormatter();

                //loop through all properties in input object
                foreach (PropertyInfo prop in Class.GetType().GetProperties())
                {
                    //if the property is serailizable then deserialize it and read its name and value, and write this in a memory object
                    if (prop.PropertyType.IsSerializable)
                    {
                        object objValue = binformat.Deserialize(StreamFile);
                        prop.SetValue(Class, objValue, null);
                    }
                }

                //close the stream
                StreamFile.Close();
            }

        }

我想要实现的是,如果在加载之前,当前对象中的属性数量发生了变化,那么我想计算流中的序列化对象的数量并循环遍历它们,然后将它们映射到当前对象中的那些而不是循环遍历当前对象中的属性。这可能吗?

1 个答案:

答案 0 :(得分:1)

没有明显的方法来计算流中的对象数量。相反,你可以:

  • 将对象计数序列化为流中的第一个对象,或
  • StreamFile.Position < StreamFile.Length
  • 时反序列化

话虽如此,你有一个更基本的问题。来自Type.GetProperties()的{​​{3}}:

  

GetProperties方法不返回特定属性   订单,例如字母或声明订单。 您的代码不得   取决于返回属性的顺序,因为那样   订单各不相同。

您的代码完全取决于此顺序不变。

作为替代方案,您可以存储属性的名称/值字典,如下所示:

public void SaveSettings(string SavedFilePath, object Class)
{
    //open the stream to write the new file
    using (Stream StreamFile = File.Open(SavedFilePath, FileMode.CreateNew))
    {
        //instantiate the binary formatter object
        BinaryFormatter binformat = new BinaryFormatter();

        //loop through all properties in input object
        var query = Class.GetType().GetProperties()
            //Make sure the property is read/write without index parameters
            .Where(p => p.GetIndexParameters().Length == 0 && p.CanRead && p.CanWrite && p.GetGetMethod() != null && p.GetSetMethod() != null)
            //if the property is serializable then serialize it and write its name and value in external file
            .Where(p => p.PropertyType.IsSerializable);

        // Create a dictionary of property names and values.
        // Note that if there are duplicate property names because a derived
        // class hides a property via a "public new" declaration, then
        // an exception will get thrown during serialization.
        var dictionary = query.ToDictionary(p => p.Name, p => p.GetValue(Class, null));

        binformat.Serialize(StreamFile, dictionary);
    }
}

public void LoadSettings(string ConfigFile, object Class)
{
    //open the stream to read the file
    using (Stream StreamFile = File.Open(ConfigFile, FileMode.Open))
    {
        //instantiate the binary formatter object
        BinaryFormatter binformat = new BinaryFormatter();

        var dictionary = (IDictionary<string, object>)binformat.Deserialize(StreamFile);

        //loop through all properties in input object
        foreach (var pair in dictionary)
        {
            var property = Class.GetType().GetProperty(pair.Key);
            if (property != null)
                property.SetValue(Class, pair.Value, null);
        }
    }
}

此方案至少对添加,删除或重新排序的属性具有一定的弹性。

话虽如此,我建议不要使用BinaryFormatter来保持对象的长期持久性。出于原因,请参阅 documentation 而是考虑XML,JSON或协议缓冲区序列化。