如何反序列化然后将数据放入表单?

时间:2015-12-25 00:46:16

标签: c# serialization deserialization generic-list binaryformatter

目标

我目前有一种保存信息的有效方法

然后,我希望程序在点击“加载”后加载已保存的状态。退出后按钮。

然后我想让程序在适当的地方显示数据

在表单中,我有两个DataGridView,一个是员工,另一个是主管。

=============================================== ==============

方式

我已将两个通用列表序列化为.dat文件

 source('custom.R')

到目前为止,在.dat文件中,我有3名员工和2名主管,我不知道如何提取信息并将其放入适当的位置

列表如下:

BinaryFormatter bFormatter = new BinaryFormatter();    
using (FileStream fs = new FileStream(FILENAME, FileMode.OpenOrCreate))
{
  bFormatter.Serialize(fs, employees);
  bFormatter.Serialize(fs, supervisors);
}

=============================================== ==========================

尝试

我对互联网和Stackoverflow进行了广泛的研究,但主要是与我的上下文无关,或者他们使用的是我不想使用的XML格式。

我认为这只是复制List<Employee> employees = new List<Employee>(); List<Supervisor> supervisors = new List<Supervisor>(); Employee e1 = new Employee(MemberJob.Employee, "Name", MemberSkills.CPlus | MemberSkills.CSharp, false); Supervisor s1 = new Supervisor(MemberJob.Supervisor, "Another name", false); employees.Add(e1); supervisors.Add(s1); 方法而只是将serialize更改为bFormatter.Serialize(fs, employees);的情况,但我在列表反序列化后仍然坚持要做什么。< / p>

bFormatter.Deserialize(fs, employees);

然后该对象会返回我需要的数据,但我无法将 BinaryFormatter bFormatter = new BinaryFormatter(); FileStream fs = File.Open(FILENAME, FileMode.Open); object obj = bFormatter.Deserialize(fs); 数据放入可用的格式,如果可能的话,它会卡在object obj我想尝试放入它回到object obj

2 个答案:

答案 0 :(得分:2)

我送给你的圣诞礼物。希望能帮助到你。 :)

namespace WpfApplication3
{
    public partial class App : Application
    {
        string path = @"C:\Users\xxx\Desktop\myFile.dat";

        public App()
        {
            InitializeComponent();

            //Test
            List<Employee> eList = new List<Employee>();
            eList.Add(new Employee("aaa"));
            eList.Add(new Employee("bbb"));

            List<Supervisor> sList = new List<Supervisor>();
            sList.Add(new Supervisor("ccc"));
            sList.Add(new Supervisor("ddd"));

            SavedInfo savedInfo = new SavedInfo();
            savedInfo.employeeList = eList;
            savedInfo.supervisorList = sList;


            SaveToFile(savedInfo); //Save to file

            SavedInfo newSaveGame = LoadFromFile(); //Load from file

            foreach (var e in newSaveGame.employeeList)
                Console.WriteLine("Employee: " + e.name);

            foreach (var e in newSaveGame.supervisorList)
                Console.WriteLine("Supervisor: " + e.name);
        }

        public void SaveToFile(SavedInfo objectToSerialize)
        {
            Stream stream = File.Open(path, FileMode.Create);
            BinaryFormatter bFormatter = new BinaryFormatter();
            bFormatter.Serialize(stream, objectToSerialize);
            stream.Close();
        }

        public SavedInfo LoadFromFile()
        {
            if (!System.IO.File.Exists(path))
                return new SavedInfo();

            SavedInfo objectToSerialize;
            Stream stream = File.Open(path, FileMode.Open);
            BinaryFormatter bFormatter = new BinaryFormatter();
            objectToSerialize = (SavedInfo)bFormatter.Deserialize(stream);
            stream.Close();
            return objectToSerialize;
        }
    }

    [Serializable()]
    public class SavedInfo
    {
        public List<Employee> employeeList = new List<Employee>();
        public List<Supervisor> supervisorList = new List<Supervisor>();
    }

    [Serializable()]
    public class Employee
    {
        public string name = "";

        public Employee(string eName)
        {
            name = eName;
        }
    }

    [Serializable()]
    public class Supervisor
    {
        public string name = "";

        public Supervisor(string eName)
        {
            name = eName;
        }
    }
}

编辑:根据jdweng的评论编辑。我认为jdweng是对的。

答案 1 :(得分:1)

与大多数其他序列化程序不同,BinaryFormatter记录了要序列化的对象的完整.Net类型元数据。正如您所指出的,它还在二进制文件中allows multiple objects to be written sequentially

因此,假设您知道二进制文件中应出现的对象序列,您可以在流上多次调用Deserialize(fs),然后将返回的对象转换为您期望的对象:

var supervisors = (List<Supervisor>)bFormatter.Deserialize(fs);
var employees = (List<Employee>)bFormatter.Deserialize(fs);

话虽如此,您的SupervisorEmployee类中的任何一个都可以直接引用彼此吗?例如,这样的事情?

[Serializable]
public class Employee : Person
{
    public Supervisor Supervisor { get; set; }
}

如果是这样,您必须通过一次调用Serialize() 来序列化员工和主管列表,因为BinaryFormatter仅在每次调用Serialize()时保留对象图关系1}}和Deserialize()。通过单独的呼叫,相互关系将会丢失。为了避免这个潜在的问题,您可以将列表打包在单个根对象中,例如List<object>

var bFormatter = new BinaryFormatter();
var root = new List<object> { supervisors, employees };
bFormatter.Serialize(fs, root);

然后,反序列化:

var bFormatter = new BinaryFormatter();
var root = (List<object>)bFormatter.Deserialize(fs);
var employees = root.OfType<IEnumerable<Employee>>().SelectMany(e => e).ToList();
var supervisors = root.OfType<IEnumerable<Supervisor>>().SelectMany(e => e).ToList();

顺便说一句,使用BinaryFormatter进行序列化可能不是长期保留数据的最佳选择。如果您对课程进行了任何更改,则需要实施Version Tolerant Serialization。另见Can strong naming cause problems with object serialization in C#?。而且BinaryFormatter完全基于文件中的类型信息构造对象的事实可能会引入反序列化不受信任数据的安全风险。