Lots of stuff wrong :( But its ok, it happens. The object you are
serializing to the membership.dat file is not an array. Ive gone ahead
and fixed up alot of the stuff that you were having issues with and Ill
explain it with comments.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace HomeWork_2
{
//Mark these classes as
//serializable so they can
//be serialized to the file.
[Serializable]
public abstract class Person
{
public abstract string Name { get; set; }
public abstract string PhoneNumber { get; set; }
public virtual void PrintInfo() { }
}
//You could also have used an
//interface for this
//not sure why an empty abstract
//class was used.
public interface IPerson
{
string Name
{
get;
set;
}
string PhoneNumber
{
get;
set;
}
void PrintInfo();
}
[Serializable]
public class PersonInfo : Person
{
//Always try to initialize variables
//with something to avoid null values.
private string name = String.Empty;
private string phoneNumber = String.Empty;
public PersonInfo()
{
}
public override string Name
{
get { return this.name; }
set { this.name = value; }
}
public override string PhoneNumber
{
get { return this.phoneNumber; }
set { this.phoneNumber = value; }
}
}
class Program
{
static void Main(string[] args)
{
//Create the list to store
//person info in and the
//binary formatter to serialize
//and deserialize it to the file.
List<PersonInfo> personInfoList = new
List<PersonInfo>(10);
//You may want to read up on
//generics a bit
BinaryFormatter binaryFormatter = new BinaryFormatter();
try
{
//Create a filestream object
//to check the length of the
//file before attempting to
//deserialize.
using (FileStream fileStream = new FileStream("membership.dat", FileMode.OpenOrCreate, FileAccess.Read))
{
if (fileStream.Length > 0)
{
//If there is data to
//deserialize, then
//deserialize it and cast
//it to the personInfoList
//object
personInfoList = (List<PersonInfo>)binaryFormatter.Deserialize(fileStream);
}
}
}
catch (IOException ex)
{
Console.WriteLine("Unable to access membership.dat file. {0}.", ex.Message);
}
catch (Exception ex)
{
//This generally isnt a good
//idea, but its a catch all for now
Console.WriteLine(ex.Message);
}
//Prime the while loop
bool quit = false;
while (!quit)
{
//Display the menu
Console.Write(" Main Menu\n\t(a) Add \n\t(b) Search \n\t(c) Print All \n\t(d) Exit\n\t-> ");
//Create a char variable to
//contain the entered character
//from the command prompt.
char selectionChar;
//Attempt to parse the input.
//If it succeeds, continue with processing.
if (Char.TryParse(Console.ReadLine(),
out selectionChar))
{
switch (selectionChar)
{
case 'a':
//Create a new person info object.
PersonInfo personInfo = new PersonInfo();
//Request the employees name
Console.Write("\nEnter Employee name: ");
personInfo.Name = Console.ReadLine();
//Request the employees phone number
Console.Write("\nEnter the employee's phone #: ");
personInfo.PhoneNumber = Console.ReadLine();
//Add a new employee to the list here
personInfoList.Add(personInfo);
break;
case 'b':
//Get the name to search for
Console.WriteLine("Enter the name of the employee whose record you want to find\n-> ");
string queryEmpName = Console.ReadLine();
//Set a variable for checking later
bool foundPerson = false;
//Iterate through the list of persons and look for the person with the supplied name.
for (int i = 0; i < personInfoList.Count; i++)
{
//If the person is found...
if (personInfoList[i].Name == queryEmpName)
{
//Let the user know and break from the loop.
Console.WriteLine("Found! Name: {0} with phone number {1}", personInfoList[i].Name, personInfoList[i].PhoneNumber);
foundPerson = true;
break;
}
//If the person is not found, the loop continues until all of the persons have been checked.
}
//If the person was not found, display a message letting the user know.
if (!foundPerson)
{
//Let the user know that the person was not found.
Console.WriteLine("The employee with name {0} was not found.", queryEmpName);
}
break;
case 'c':
//Iterate through the list of persons and display their information.
for (int i = 0; i < personInfoList.Count; i++)
{
//Display each persons information.
Console.WriteLine("{0}
- Name: {1} Phone Number: {2}", /*Up i by one because arrays are zero
indexed.*/ (i + 1).ToString(), personInfoList[i].Name, personInfoList[i].PhoneNumber);
}
break;
case 'd':
try
{
//Create a file stream object to serialize the data to.
using (FileStream fileStream = new FileStream("membership.dat", FileMode.OpenOrCreate, FileAccess.Write))
{
binaryFormatter.Serialize(fileStream, personInfoList);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
//Pause the console so the message can be read.
Console.ReadLine();
}
finally
{
//Set the quit variable so the loop will exit.
quit = true;
}
break;
default:
Console.WriteLine("Invalid selection entered.");
break;
}
}
else //If the input couldnt be parsed, display an error.
{
Console.WriteLine("Invalid selection entered");
}
}
}
}
}
//--------------
//-NO MORE CODE-
//--------------
So
basically, when you load it, it will display a menu asking you for a
choice. If you enter a lowercase letter a - d it will continue
processing but anything else and it will prompt for and let you know
you input something invalid. It will then let you make another choice.
Generic collections,
as I have used in the collection of PersonInfo objects, are really a
nice thing. Theyre easier to work with than raw arrays and they
dynamically resize themselves rather than having a set size all the
time much like an array. Generics are much more useful than just using in collection classes too.
As well as being easier to work with, the generic List class (denotated as List<Type>)
where Type is the type of object you wish to store in the strongly
typed collection. This works much better than the ArrayList class
(which I havent used for quite some time due to me liking type safety)
but when you create a generic List collection, you can only store
objects of the type you have specified in it. In later learning, you
will probably come across interfaces and base classes where you will be
able to store any object that implements an particular interface or
base class and such... But that might be awhile, lol.
Some examples...
List<string> //A generic collection of strings
List<int> //A generic collection of integer values
List<MyClass> //A generic collection of class objects
List<IMyInterface> //A generic collection of interface objects
I
commented alot of the code to help you figure out what was going on
instead of just giving you the code, so if you wanna learn, check my
comments and go through the code and try to figure it out for yourself.
The
whole issue with your serialization/deserialization was that you were
serializing objects of type PersonInfo to the file, but you were
attempting to deserialize objects of type PersonInfo[] which was giving
you an exception. Just check it out, and be sure to go through it
because thats how you learn and if you have any questions at all, feel
free to ask. I tend to talk about, but I always figure I can never do
enough explaining of a concept :) More always helps.