C# 如何反序列化并将数据转换为表单?
目标 我目前有保存信息的有效方法 然后,我希望程序在退出后单击“加载”按钮加载保存的状态 然后我希望程序在适当的位置显示数据 在表单中,我有两个DataGridView,一个用于员工,另一个用于主管 ============================================================= 方法 我已将两个通用列表序列化为一个.dat文件C# 如何反序列化并将数据转换为表单?,c#,serialization,deserialization,generic-list,binaryformatter,C#,Serialization,Deserialization,Generic List,Binaryformatter,目标 我目前有保存信息的有效方法 然后,我希望程序在退出后单击“加载”按钮加载保存的状态 然后我希望程序在适当的位置显示数据 在表单中,我有两个DataGridView,一个用于员工,另一个用于主管 ============================================================= 方法 我已将两个通用列表序列化为一个.dat文件 BinaryFormatter bFormatter = new BinaryFormatter(); using (
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);
然后该对象返回我需要的数据,但我无法将
对象obj
数据转换为可用格式,它被困在对象obj
中。如果可能,我想尝试将其放回员工列表中与大多数其他序列化程序不同,它记录被序列化对象的完整.Net类型元数据。正如您所注意到的,它也存在于二进制文件中
因此,假设您知道二进制文件中应该出现的对象序列,您可以在流上多次调用反序列化(fs)
,然后将返回的对象强制转换为您期望的:
var supervisors = (List<Supervisor>)bFormatter.Deserialize(fs);
var employees = (List<Employee>)bFormatter.Deserialize(fs);
如果是这样,您必须在对serialize()
的一次调用中序列化员工和主管列表,因为BinaryFormatter
仅在对serialize()
和反序列化()
的每次调用中保留对象图关系。单独通话时,相互关系将丢失。为避免此潜在问题,您可以将列表打包到单个根对象中,例如列表
:
var bFormatter=new BinaryFormatter();
var root=新列表{主管,员工};
序列化(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();
var bFormatter=new BinaryFormatter();
var root=(List)bFormatter.Deserialize(fs);
var employees=root.OfType();
var supervisors=root.OfType().SelectMany(e=>e.ToList();
顺便说一句,使用BinaryFormatter
进行序列化可能不是长期保存数据的最佳选择。如果在类中进行任何更改,则需要实现。另见。而且,BinaryFormatter
完全基于文件中的类型信息构造对象这一事实会给反序列化不可信数据带来安全风险 我送给你的圣诞礼物。希望有帮助。:)
命名空间WpfApplication3
{
公共部分类应用程序:应用程序
{
字符串路径=@“C:\Users\xxx\Desktop\myFile.dat”;
公共应用程序()
{
初始化组件();
//试验
列表列表=新列表();
列表添加(新员工(“aaa”);
列表添加(新员工(“bbb”);
List sList=新列表();
增加(新主管(“ccc”);
新增(新监管人(“ddd”);
SavedInfo SavedInfo=新的SavedInfo();
savedInfo.employeeList=eList;
savedInfo.supervisorList=sList;
SaveToFile(savedInfo);//保存到文件
SavedInfo newSaveGame=LoadFromFile();//从文件加载
foreach(newSaveGame.employeeList中的变量e)
Console.WriteLine(“员工:+e.name”);
foreach(newSaveGame.supervorlist中的变量e)
Console.WriteLine(“主管:+e.name”);
}
public void SaveToFile(SavedInfo objectToSerialize)
{
Stream=File.Open(路径,FileMode.Create);
BinaryFormatter bFormatter=新的BinaryFormatter();
序列化(流、对象序列化);
stream.Close();
}
public SavedInfo LoadFromFile()
{
如果(!System.IO.File.Exists(path))
返回新的SavedInfo();
SavedInfo对象序列化;
Stream=File.Open(路径,FileMode.Open);
BinaryFormatter bFormatter=新的BinaryFormatter();
objectToSerialize=(SavedInfo)bFormatter.Deserialize(流);
stream.Close();
返回对象序列化;
}
}
[可序列化()]
公共类SavedInfo
{
public List employeeList=新列表();
public List supervisorList=新列表();
}
[可序列化()]
公营雇员
{
公共字符串名称=”;
公共雇员(字符串名称)
{
name=eName;
}
}
[可序列化()]
公营班主任
{
公共字符串名称=”;
公共主管(字符串名称)
{
name=eName;
}
}
}
编辑:根据jdweng的评论进行编辑。我认为jdweng是对的。首先,这是一种糟糕的数据存储方式,因为每次都必须保存两个列表。第二我敢打赌,只要稍加努力,主管就可以从员工那里继承,这样您只需要保存一个列表。反序列化列表后,如果使用DGV。您可以将它们设置为数据源,数据将自动显示。您是否在询问如何从列表中填充DataGridView?或者如何反序列化到您需要的列表中?@puropoix Supervisor确实继承自员工,我如何将其设置为数据源?但在此之前,我如何正确地反序列化?@Ciara-如何反序列化到列表为什么不创建包含这两个列表的类。然后序列化该类。
[Serializable]
public class Employee : Person
{
public Supervisor Supervisor { get; set; }
}
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();
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;
}
}
}