Using the 'DataContract and 'DataMember Attributes in System.Runtime.Serialization you can easily serialize and de-serialize a Class. The code shown here is as simple as possible, to illustrate the techniques involved.
Start with:
1. A Windows Forms Project with:
a. a TextBox, 'textBox1
b. ListBox, 'listBox1
c. 4 buttons: 'btnAdd, 'btnDelete, 'btnSave, 'btnLoad
2. This simple class:
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Windows.Forms;
namespace March8_SimpleDB
{
[DataContract]
public class Users
{
[DataMember]
public List<string> UserList { set; get; }
[DataMember]
public string FileLocation { set; get; }
private static DataContractSerializer theSerializer;
public Users()
{
UserList = new List<string>();
FileLocation = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
FileLocation = Path.Combine(FileLocation, @"DefaultUsersFile.xml");
}
public void Add(string newUser)
{
UserList.Add(newUser);
}
public void Remove(string xUser)
{
UserList.Remove(xUser);
}
public bool Contains(string user)
{
return (UserList.Contains(user));
}
public static void Serialize(Users theUsers)
{
if(theSerializer == null) theSerializer = new DataContractSerializer(typeof(Users));
try
{
using (FileStream stream = new FileStream(theUsers.FileLocation, FileMode.Create))
{
theSerializer.WriteObject(stream, theUsers);
}
}
catch (Exception)
{
throw new InvalidDataContractException("Can't save file to: " + theUsers.FileLocation);
}
MessageBox.Show("file successfully saved");
}
public static Users DeSerialize(Users theUsers)
{
if (theSerializer == null) theSerializer = new DataContractSerializer(typeof(Users));
Users result = null;
using (FileStream stream = new FileStream(theUsers.FileLocation, FileMode.Open))
{
try
{
result = (Users) theSerializer.ReadObject(stream);
theUsers.UserList = result.UserList;
}
catch (Exception)
{
throw new InvalidDataContractException("Can't read file at: " + theUsers.FileLocation);
}
}
MessageBox.Show("file read successfully");
return result;
}
}
}</string></string>
Here's how you would serialize and de-serialize this class in the "main Form:"
using System;
using System.Windows.Forms;
namespace March8_SimpleDB
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Users TheUsers;
private void Form1_Load(object sender, EventArgs e)
{
TheUsers = new Users();
}
private void btnAdd_Click(object sender, EventArgs e)
{
string text = textBox1.Text;
if (string.IsNullOrWhiteSpace(text)) return;
if (TheUsers.Contains(text)) return;
TheUsers.Add(text);
listBox1.Items.Add(text);
}
private void btnDelete_Click(object sender, EventArgs e)
{
object selection = listBox1.SelectedItem;
if (selection == null) return;
string text = selection.ToString();
TheUsers.Remove(text);
listBox1.Items.Remove(selection);
}
private void btnSave_Click(object sender, EventArgs e)
{
TheUsers.UserList.Clear();
foreach (var itm in listBox1.Items)
{
TheUsers.Add(itm.ToString());
}
Users.Serialize(TheUsers);
}
private void btnLoad_Click(object sender, EventArgs e)
{
Users.DeSerialize(TheUsers);
listBox1.Items.Clear();
foreach (string user in TheUsers.UserList)
{
listBox1.Items.Add(user);
}
}
}
}
Notes:
1. Yes, you can use 'DataContract/'DataMember to serialize a Class that inherits from a Generic List, or Dictionary, but in order to do that a work-around is required because the Serializer will write only the Items in the LIst or KeyValue Pairs in the Dictionary, and will ignore any other Fields/Properties marked with 'DataMember.
2. Static Class members will be ignored by the Serilializer.
3. You can serialize Fields with 'DataContract; I think it's better practice, for many reasons, to get in the habit of using Properties rather than Fields. Keep in mind that the upcoming C# 6.0 will allow easy in-line initialization of Properties.
Comments, suggestions, welcome.