【问题标题】:How to deserialize and then put data into form?如何反序列化然后将数据放入表单?
【发布时间】:2016-03-31 06:33:32
【问题描述】:

目标

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

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

然后我希望程序将数据显示在适当的位置

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

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

方法

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

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

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

名单如下:

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);

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

尝试

我在 Internet 和 Stackoverflow 上进行了广泛的查看,但主要是它与我的上下文无关,或者他们使用的是我不想使用的 XML 格式。

我认为这只是复制 serialize 方法并将 bFormatter.Serialize(fs, employees); 更改为 bFormatter.Deserialize(fs, employees); 的情况,但我在反序列化列表后被困在做什么。

 BinaryFormatter bFormatter = new BinaryFormatter();
 FileStream fs = File.Open(FILENAME, FileMode.Open);
 object obj = bFormatter.Deserialize(fs);

然后该对象带回我需要的数据,但我无法将object obj 数据转换为可用格式,如果可能,它会卡在object obj 中,我想尝试将其放回@987654329 @

【问题讨论】:

  • 首先,这是一种存储数据的糟糕方式,因为您每次都必须保存两个列表。第二。稍加努力,我敢打赌 Supervisor 可以从 Employee 继承,这样你只需要保存一个列表。反序列化列表后,如果您使用的是 DGV。您可以将它们设置为数据源,数据将自动显示。
  • 您是否在问如何从列表中填充 DataGridViews?或者如何反序列化成你需要的列表?
  • @Plutonix Supervisor 确实继承自 Employee,我如何将它们设置为数据源?但在此之前我将如何正确反序列化?
  • @Ciara - 如何反序列化到列表中
  • 为什么不创建一个包含这两个列表的类。然后序列化类。

标签: c# serialization deserialization generic-list binaryformatter


【解决方案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() 和@987654334 的每次调用中保留对象图关系@。使用单独的调用,相互关系将丢失。为避免此潜在问题,您可以将列表打包到单个根对象中,例如 List&lt;object&gt;

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 完全基于文件内的类型信息构造对象这一事实可能会引入反序列化不受信任数据的安全风险。

【讨论】:

    【解决方案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是对的。

    【讨论】:

      猜你喜欢
      • 2017-12-23
      • 2020-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多