C#流反序列化循环的方式



所以我正在开发一个windows窗体应用程序,并将对象插入到列表框(sessionListBox(中。我在不同的论坛上创建每个对象,而不是最终确定所有对象成为一个。这意味着当我流式传输/加载我保存的文件时,它只会加载一个对象。有没有一种方法可以循环流,让它带回多个对象,我该怎么做?

对于c#和编程来说是非常新的,所以如果它是一个明显的解决方案,请对我来说轻松:(

private void saveButton_Click(object sender, EventArgs e)
{

SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
saveFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
{
string FileName = saveFileDialog.FileName;
Stream stream = File.Open(FileName, FileMode.Create);
BinaryFormatter bformatter = new BinaryFormatter();

Console.WriteLine("Writing Workout Information");
foreach (Workout w in sessionListBox.Items)
{
bformatter.Serialize(stream, w);
}
stream.Close();
}

}
private void loadButton_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
openFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
if (openFileDialog.ShowDialog(this) == DialogResult.OK)
{
string FileName = openFileDialog.FileName;
Stream stream = File.Open(FileName, FileMode.Open);
BinaryFormatter bformatter = new BinaryFormatter();


if (stream.Length != 0)
{
Console.WriteLine("");
Workout temp = (Workout)bformatter.Deserialize(stream);
sessionListBox.Items.Add(temp);
}
stream.Close();

}
}

您只能对序列化的内容进行反序列化。如果要序列化数组或列表,请将数据放在列表中,然后将数据作为列表读取。

此外:不要试图以你的形式做每件事。制作单独的类来做单独的事情(阅读一篇关于SOLID原理的文章(。这将使代码更容易重用、更容易理解、编写文本、调试代码以及更容易更改。

因此,我创建了一个单独的类来存储和检索训练序列。我对外界隐瞒训练的保存格式。我所知道的是,即使在程序重新启动后,训练也可以保存和检索。

static class WorkoutRepository
{
public static void Save(IEnumerable<Workout> workouts, string fileName)
{
BinaryFormatter formatter = new BinaryFormatter();
using (Stream stream = File.Open(fileName, FileMode.Create))
{
formatter.Serialize(stream, workouts.ToList());
}
}
public static IEnumerable<WorkOut> Load(string fileName)
{
BinaryFormatter formatter = new BinaryFormatter();
using (Stream stream = File.Open(fileName, FileMode.Open))
{
var obj = formatter.Deserialize(stream);
if (obj is IEnumerable<Workout> workouts)
{
return workouts;
}
else
{
// TODO: throw exception?
}
}
}
}

用法:

List<Workout> workoutsToSave = ...
string fileName = ...
// Save:
WorkoutRepository.Save(workouts, fileName);
// Load:
var workOuts = WorkoutRepository.Load(fileName).ToList();

此代码是可重用的。好的一面是,您隐藏了保存数据的格式:如果您决定将数据保存为数组、XML格式或数据库,则用户(=代码,而不是运算符(不必更改。

代码更容易进行单元测试,如果将窗口处理与序列化分离,代码将更容易理解。

以您的形式:

IEnumerable<Workout> FetchWorkouts()
{
using (var dlg = new OpenFileDlg())
{
...
return WorkoutRepository.Load(dlg.Filename);
}
}
private void LoadWorkouts()
{
var fetchedWorkOuts = this.FetchWorkOuts();
this.ShowWorkOuts(fetchedWorkOuts);
}
private void LoadButton_Clicked(object sender, ...)
{
this.LoadWorkouts();
}

通过将数据与存储位置和显示方式分开,可以很容易地更改这一点:在菜单选择上加载训练,而不是单击按钮?是否在DataGridView而不是ListBox中显示训练?从数据库中获取训练:总是在一个相当小的方法中进行更改,该方法有一个精确的任务。

最新更新