This is one of the most common questions you guys get here so forgive me but I cannot get past this no matter how hard I search.
I am building a keychain application for a project in Windows Forms Application, and for the purpose of understanding this concept as easily as possible I went with a List<> rather than Dictionary//iList
This is the Class I have been using:
public class Account
{
public static List<Account> myAccountList = new List<Account>();
public string Domain; //this is supposed to be google/skype/facebook
public string Email;
public string Username;
public string Password;
public Account (string domain, string email, string username, string password)
{
Domain = domain;
Email = email;
Username = username;
Password = password;
myAccountList.Add(new Account(domain, email, username, password)); //constructor calls the new list instance
}
private static void SaveToFile()
{
System.IO.File.WriteAllLines(@accountdb.txt, myAccountList);
}
private static void ReadFromFile() // this is meant to be used as authentication in my main form, it isn't necessary right now..
{
System.IO.File.ReadAllLines(@accountdb.txt);
}
}
I have a couple issues with this:
System.IO
The Button Click event that calls the Constructor:
private void buttonSave_Click(object sender, EventArgs e)
{
string domain, email, username, password;
domain = comboboxDomain.Text;
email = textboxEmail.Text;
username = textboxUsername.Text;
password = textboxPassword.Text;
//Checking for correct EMAIL
if (!textboxEmail.Text.Contains("@") && (!textboxEmail.Text.Contains(".")))
{
MessageBox.Show("Invalid Email Format");
}
else
{
Account account = new Account(domain, email, username, password);
}
}
WriteAllLines
expects an string[]
as the second parameter. So you need to create a way to represent a single Account
object as a string. The easiest way is to override the ToString
method. Then use the Linq Select
method to select them.
Also, it would be better if the Account
class did not also contain the list of accounts. That should really be a separate class. Try something like this:
void Main()
{
var accountList = new AccountList();
//Save a few accounts to the file
Account a1 = new Account("Google", "GoogleEmail", "GoogleUser", "GooglePass");
accountList.Add(a1);
Account a2 = new Account("Netflix", "NetflixEmail", "NetflixUser", "NetflixPass");
accountList.Add(a2);
AccountList.SaveToFile(@"g:\test\accounts.txt", accountList);
//Load the accounts from the file
AccountList aList2 = AccountList.ReadFromFile(@"g:\test\accounts.txt");
aList2.Dump();
}
public class AccountList
{
private List<Account> accounts;
public IEnumerable<Account> Accounts { get { return accounts;} }
public AccountList()
{
this.accounts = new List<Account>();
}
public void Add(Account a)
{
accounts.Add(a);
}
public static void SaveToFile(string filename, AccountList accounts)
{
//Selects all the `Account` instances and creates a string[]
System.IO.File.WriteAllLines(filename, accounts.Accounts.Select(a => $"{a}").ToArray());
}
public static AccountList ReadFromFile(string filename) // this is meant to be used as authentication in my main form, it isn't necessary right now..
{
var result = new AccountList();
//Read each line from the file and create an Account instance.
foreach (var line in System.IO.File.ReadAllLines(filename))
{
if (!string.IsNullOrWhiteSpace(line))
{
var parts = line.Split(',');
if (parts.Length == 4)
{
Account a = new Account(parts[0], parts[1], parts[2], parts[3]);
result.Add(a);
}
}
}
return result;
}
}
public class Account
{
public string Domain; //this is supposed to be google/skype/facebook
public string Email;
public string Username;
public string Password;
public Account(string domain, string email, string username, string password)
{
Domain = domain;
Email = email;
Username = username;
Password = password;
}
public override string ToString()
{
return $"{Domain},{Email},{Username},{Password}";
}
}