C
C#15mo ago
Mekasu0124

✅ Learning C# through console app

// Program.cs
using PhasmoTriviaConsole.Services;

namespace PhasmoTriviaConsole;

class Program
{
private Database _db;
public Program(Database db)
{
_db = db;
UserInfo UserName = new UserInfo(db.LoadUser());
}

public string UserName { get; set; }
}

// /Services/Database.cs
using System.Text.Json;

namespace PhasmoTriviaConsole.Services;

internal class Database
{
private const string dbFile = "user.json";

public UserInfo LoadUser()
{
if (File.Exists(dbFile))
{
var dbInfo = File.ReadAllText(dbFile);
UserInfo info = JsonSerializer.Deserialize<UserInfo>(dbInfo);
return info;
}
else
{
return new UserInfo();
}
}

public void SaveUser(UserInfo info)
{
var content = JsonSerializer.Serialize(info);
File.WriteAllText(dbFile, content);
}
}

// /Models/UserModel.cs
namespace PhasmoTriviaConsole;

public class UserInfo
{
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string DOB { get; set; }
}
// Program.cs
using PhasmoTriviaConsole.Services;

namespace PhasmoTriviaConsole;

class Program
{
private Database _db;
public Program(Database db)
{
_db = db;
UserInfo UserName = new UserInfo(db.LoadUser());
}

public string UserName { get; set; }
}

// /Services/Database.cs
using System.Text.Json;

namespace PhasmoTriviaConsole.Services;

internal class Database
{
private const string dbFile = "user.json";

public UserInfo LoadUser()
{
if (File.Exists(dbFile))
{
var dbInfo = File.ReadAllText(dbFile);
UserInfo info = JsonSerializer.Deserialize<UserInfo>(dbInfo);
return info;
}
else
{
return new UserInfo();
}
}

public void SaveUser(UserInfo info)
{
var content = JsonSerializer.Serialize(info);
File.WriteAllText(dbFile, content);
}
}

// /Models/UserModel.cs
namespace PhasmoTriviaConsole;

public class UserInfo
{
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string DOB { get; set; }
}
I have decided to take a step back from Avalonia to just focus on learning C# through a console application. This is all I have in my console app. I cannot for the life of me figure out how to get access to the username stored within the UserInfo that is returned from the load function. Any suggestions would be great
70 Replies
Thinker
Thinker15mo ago
You're not actually setting UserName in the constructor of Program, that's a variable called UserName which is shadowing the property.
Mekasu0124
Mekasu0124OP15mo ago
so remove UserInfo from the decorator?
Thinker
Thinker15mo ago
wdym "decorator"?
Mekasu0124
Mekasu0124OP15mo ago
- UserInfo UserName = new UserInfo(db.LoadUser());
+ UserName = new UserInfo(db.LoadUser());
- UserInfo UserName = new UserInfo(db.LoadUser());
+ UserName = new UserInfo(db.LoadUser());
Thinker
Thinker15mo ago
yep
Mekasu0124
Mekasu0124OP15mo ago
ok it still doesn't like UserInfo(db.LoadUser()); so what do I have wrong there?
Pobiega
Pobiega15mo ago
UserInfo is your class. Calling it like that tries to invoke its constructor but you only have the default parameterless constructor for that class
Mekasu0124
Mekasu0124OP15mo ago
I'm not going to lie. I was modeling this after the picture of my avalonia code
Pobiega
Pobiega15mo ago
well, I suggest you stop doing that
Mekasu0124
Mekasu0124OP15mo ago
bet what do you mean?
Pobiega
Pobiega15mo ago
I mean exactly that. Look at your UserInfo class.
public class UserInfo
{
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string DOB { get; set; }
}
public class UserInfo
{
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string DOB { get; set; }
}
do you see any constructors?
Mekasu0124
Mekasu0124OP15mo ago
that's how I was taught to do those. I assume no? What's the proper way to do it?
Pobiega
Pobiega15mo ago
no thats fine its a very basic mutable POCO
Mekasu0124
Mekasu0124OP15mo ago
that's even how the Todo guide on avalonia's website says to do it poco?
Pobiega
Pobiega15mo ago
this isnt avalonia.
Mekasu0124
Mekasu0124OP15mo ago
right
Pobiega
Pobiega15mo ago
"plain old Csharp object"
Mekasu0124
Mekasu0124OP15mo ago
ah. nice acronym
Pobiega
Pobiega15mo ago
its essentially a simple object it just stores some data. but look at the code you suggested UserInfo(db.LoadUser()); what do you think this does? it has 2 parts, the UserInfo(...) and the db.LoadUser()
Mekasu0124
Mekasu0124OP15mo ago
tries to pass a database function to a class
Pobiega
Pobiega15mo ago
almost, but not quite it runs the function and tries to pass the result to the constructor of your class
Mekasu0124
Mekasu0124OP15mo ago
ok. that's not the behaviour I wanted. I wanted it to return the user object from the json file
Pobiega
Pobiega15mo ago
UserInfo info = db.LoadUser();
UserInfo username = new UserInfo(info);
UserInfo info = db.LoadUser();
UserInfo username = new UserInfo(info);
thats what you are doing, more or less
Mekasu0124
Mekasu0124OP15mo ago
hm.. ok I think I'm doign this wrong anyways. The program needs to create a new json file with a "setup": 0 thing in it. This is then used in the Program.cs file to check whether the user has setup their account or not. If not, then it launches a setup, otherwise, it pulls the user's username from the userinfo object from the json file
class Program
{
private Database _db;
public Program()
{
var dbInfo = File.ReadAllText("/Services/user.json");
int setupCheck = JsonSerializer.Deserialize(dbInfo);

if (setupCheck == 0)
{
// launch user setup class
}
else
{
// load user info
}

DateTime date = DateTime.UtcNow;
Menu menu = new Menu();
menu.ShowMenu(username, date);
}
class Program
{
private Database _db;
public Program()
{
var dbInfo = File.ReadAllText("/Services/user.json");
int setupCheck = JsonSerializer.Deserialize(dbInfo);

if (setupCheck == 0)
{
// launch user setup class
}
else
{
// load user info
}

DateTime date = DateTime.UtcNow;
Menu menu = new Menu();
menu.ShowMenu(username, date);
}
this is how my brain imagines this is supposed to go. What do you think?
Pobiega
Pobiega15mo ago
that seems very convoluted
Mekasu0124
Mekasu0124OP15mo ago
well I missed creating the json file. fuck
Pobiega
Pobiega15mo ago
isnt it a lot easier to just check if the user.json file exists or not?
Mekasu0124
Mekasu0124OP15mo ago
yea true didn't think about that
Pobiega
Pobiega15mo ago
and even abstract that
Mekasu0124
Mekasu0124OP15mo ago
ok how do I abstract it?
Pobiega
Pobiega15mo ago
well, the file might exist but contain invalid data. so try to deserialize it, and if that fails, either throw or return null or something somehow indicate to your program that we need to create and save a new user
Mekasu0124
Mekasu0124OP15mo ago
ok let me see what I can come up with
Pobiega
Pobiega15mo ago
hint: a method that returns a User? seems reasonable
Mekasu0124
Mekasu0124OP15mo ago
class Program
{
private Database _db;
private const string dbFile = "/Services/user.json";

public Program(Database db)
{
if (CheckUser(db) != null)
{
UserName = db.LoadUser();
}
else
{
UserProfile createUser = new UserProfile();
createUser.Start();
}
}

public UserInfo CheckUser(Database db)
{
if (File.Exists(dbFile))
{
var dbInfo = File.ReadAllText(dbFile);
UserInfo info = JsonSerializer.Deserialize<UserInfo>(dbInfo);
return info;
}
else
{
return null;
}
}

public UserInfo UserName { get; set; }
}
class Program
{
private Database _db;
private const string dbFile = "/Services/user.json";

public Program(Database db)
{
if (CheckUser(db) != null)
{
UserName = db.LoadUser();
}
else
{
UserProfile createUser = new UserProfile();
createUser.Start();
}
}

public UserInfo CheckUser(Database db)
{
if (File.Exists(dbFile))
{
var dbInfo = File.ReadAllText(dbFile);
UserInfo info = JsonSerializer.Deserialize<UserInfo>(dbInfo);
return info;
}
else
{
return null;
}
}

public UserInfo UserName { get; set; }
}
what do you think about this?
Pobiega
Pobiega15mo ago
Pretty good, but I'd like to change a few things first, UserInfo, can we rename that to User? CheckUser actually returns the user, so maybe.. LoadUser or GetSavedUser? and finally, you are passing a Database db into that method but never using it I'd probably write it like...
private static User? LoadUser()
{
const string file = "user.json";

if (!File.Exists(file))
return null;

try
{
var content = File.ReadAllText(file);
return JsonSerializer.Deserialize<User>(content);
}
catch (Exception ex)
{
Console.WriteLine($"[ERROR] Couldn't read stored user file: {ex.Message}");
Console.WriteLine(ex.StackTrace);
return null;
}
}
private static User? LoadUser()
{
const string file = "user.json";

if (!File.Exists(file))
return null;

try
{
var content = File.ReadAllText(file);
return JsonSerializer.Deserialize<User>(content);
}
catch (Exception ex)
{
Console.WriteLine($"[ERROR] Couldn't read stored user file: {ex.Message}");
Console.WriteLine(ex.StackTrace);
return null;
}
}
Mekasu0124
Mekasu0124OP15mo ago
that's because I have a database class in /Services/Database.cs that has a LoadUser funciton
Pobiega
Pobiega15mo ago
Yeah but you never use it 🙂
Mekasu0124
Mekasu0124OP15mo ago
I have a database class that has a load user function. It's supposed to return the user, and then the UserName in the Program.cs file is supposed to set UserName equal to the username that is stored in the json file after created. If the file doesn't exist, then it returns a blank user. Can we use that instead?
Pobiega
Pobiega15mo ago
I'm sorta thinking this new method can fully replace that one
public static void Main()
{
var user = LoadUser();

if (user is null)
{
user = CreateNewUser();
SaveUser(user);
}

// we now know that user has good data.
}
public static void Main()
{
var user = LoadUser();

if (user is null)
{
user = CreateNewUser();
SaveUser(user);
}

// we now know that user has good data.
}
you could move LoadUser and SaveUser into your database class if you wanted to
Mekasu0124
Mekasu0124OP15mo ago
ok so going with my database class, how would I use that?
Pobiega
Pobiega15mo ago
public static void Main()
{
var db = new Database();
var user = db.LoadUser();

if (user is null)
{
user = CreateNewUser();
db.SaveUser(user);
}

// we now know that user has good data.
}
public static void Main()
{
var db = new Database();
var user = db.LoadUser();

if (user is null)
{
user = CreateNewUser();
db.SaveUser(user);
}

// we now know that user has good data.
}
note that I assume you changed your db loaduser here to return null
Mekasu0124
Mekasu0124OP15mo ago
class Program
{
private Database _db;
private const string dbFile = "/Services/user.json";

public Program(Database db)
{
var user = db.LoadUser();

if (user != null)
{
UserName = user.Username;
}
else
{

}
}

public string UserName { get; set; }
}
class Program
{
private Database _db;
private const string dbFile = "/Services/user.json";

public Program(Database db)
{
var user = db.LoadUser();

if (user != null)
{
UserName = user.Username;
}
else
{

}
}

public string UserName { get; set; }
}
using System.Text.Json;

namespace PhasmoTriviaConsole.Services;

internal class Database
{
private const string dbFile = "user.json";

public User LoadUser()
{
if (File.Exists(dbFile))
{
var dbInfo = File.ReadAllText(dbFile);
User info = JsonSerializer.Deserialize<User>(dbInfo);
return info;
}
else
{
return new User();
}
}

public void SaveUser(User info)
{
var content = JsonSerializer.Serialize(info);
File.WriteAllText(dbFile, content);
}
}
using System.Text.Json;

namespace PhasmoTriviaConsole.Services;

internal class Database
{
private const string dbFile = "user.json";

public User LoadUser()
{
if (File.Exists(dbFile))
{
var dbInfo = File.ReadAllText(dbFile);
User info = JsonSerializer.Deserialize<User>(dbInfo);
return info;
}
else
{
return new User();
}
}

public void SaveUser(User info)
{
var content = JsonSerializer.Serialize(info);
File.WriteAllText(dbFile, content);
}
}
no? it returns an empty user. I'll go change it
Pobiega
Pobiega15mo ago
Yeah that doesnt really make sense if you ask me because then we can't easily check if we need to make a new user or not
Mekasu0124
Mekasu0124OP15mo ago
I changed it to return null
Pobiega
Pobiega15mo ago
great again, I'll post my method for this
private static User? LoadUser()
{
const string file = "user.json";

if (!File.Exists(file))
return null;

try
{
var content = File.ReadAllText(file);
return JsonSerializer.Deserialize<User>(content);
}
catch (Exception ex)
{
Console.WriteLine($"[ERROR] Couldn't read stored user file: {ex.Message}");
Console.WriteLine(ex.StackTrace);
return null;
}
}
private static User? LoadUser()
{
const string file = "user.json";

if (!File.Exists(file))
return null;

try
{
var content = File.ReadAllText(file);
return JsonSerializer.Deserialize<User>(content);
}
catch (Exception ex)
{
Console.WriteLine($"[ERROR] Couldn't read stored user file: {ex.Message}");
Console.WriteLine(ex.StackTrace);
return null;
}
}
its a good idea to wrap any File.Read/Write methods in try/catch since file IO can fail for whatever reason you can remove the printing and static and const file path stuff as needed
Mekasu0124
Mekasu0124OP15mo ago
ok I updated it to be wrapped in the try/catch ok so I've started a class in /UserSetup/UserSetup.cs named UserSetup How do I call that into the else statement in my Program.cs?
Pobiega
Pobiega15mo ago
Why is that its own class?
Mekasu0124
Mekasu0124OP15mo ago
because I like to keep my code and program parts separate
using PhasmoTriviaConsole.Services;

namespace PhasmoTriviaConsole;

class Program
{
private Database _db;

public Program(Database db)
{
var user = db.LoadUser();

if (user != null)
{
UserName = user.Username;
}
else
{

}
}

public string UserName { get; set; }
}
using PhasmoTriviaConsole.Services;

namespace PhasmoTriviaConsole;

class Program
{
private Database _db;

public Program(Database db)
{
var user = db.LoadUser();

if (user != null)
{
UserName = user.Username;
}
else
{

}
}

public string UserName { get; set; }
}
Pobiega
Pobiega15mo ago
This is somewhat cursed to the honest You are running all your app logic in the program constructor please don't do that. And if you just want to have a way to create users, make a static User CreateUser() method, either in UserSetup or in User itself
Mekasu0124
Mekasu0124OP15mo ago
ok I made it static. How do I call it in the else statement in program.cs
Pobiega
Pobiega15mo ago
UserSetup.CreateUser() but it returns a void atm, so thats not good Actually, lets take a step back. Do you understand methods, return types and constructors?
Mekasu0124
Mekasu0124OP15mo ago
it doesn't like this
Pobiega
Pobiega15mo ago
how so
Mekasu0124
Mekasu0124OP15mo ago
Pobiega
Pobiega15mo ago
Ah, you have a namespace AND a type both called UserSetup thats a no-no
Mekasu0124
Mekasu0124OP15mo ago
I didn't do anything. It generated that itself when I created the file
Pobiega
Pobiega15mo ago
well yes but if you make a folder and a type in that folder have the same name... thats what you get the default convention is that your directory structure => your namespaces
Mekasu0124
Mekasu0124OP15mo ago
ok I fixed it. I just renamed the file and put in the using statement
MODiX
MODiX15mo ago
Pobiega
Actually, lets take a step back. Do you understand methods, return types and constructors?
Quoted by
React with ❌ to remove this embed.
Pobiega
Pobiega15mo ago
I don't ask to be an ass, it just seems that sometimes you just throw code at the screen and see what sticks kinda Like the UserInfo(db.LoadUser()) thing above
Mekasu0124
Mekasu0124OP15mo ago
I give a type like string, bool, User when one is needed. Otherwise, I just use void when I don't need to return anything
Pobiega
Pobiega15mo ago
Well yes. And you understand that calling a method will return something, unless that methods type is void, right? And thats how we pass information around
Mekasu0124
Mekasu0124OP15mo ago
yes
Pobiega
Pobiega15mo ago
So explain to me the reason why CreateUser would have a void return type?
Mekasu0124
Mekasu0124OP15mo ago
I changed it to return a user so that program can still access the user
Pobiega
Pobiega15mo ago
good
Mekasu0124
Mekasu0124OP15mo ago
thank you for your help 🙂
class Program
{
public Program(Database db)
{
var user = db.LoadUser();

if (user != null)
{
UserName = user.Username;
}
else
{
user = Setup.CreateUser(db);
UserName = user.Username;
}

GameMenu.ShowMenu(UserName, DateTime.UtcNow);
}

public string UserName { get; set; }
}
class Program
{
public Program(Database db)
{
var user = db.LoadUser();

if (user != null)
{
UserName = user.Username;
}
else
{
user = Setup.CreateUser(db);
UserName = user.Username;
}

GameMenu.ShowMenu(UserName, DateTime.UtcNow);
}

public string UserName { get; set; }
}
so I just tried to run my program to test what I have so far, and it told me that Program doesn't have a static main method suitable for entry point so what did I do wrong here? so apparently I'm missing
public static void Main(string[] args) {}
public static void Main(string[] args) {}
so how would I work that into my Program.cs file here?
Thinker
Thinker15mo ago
Usually Program doesn't have a constructor, but if you do want to have that then you could do this instead
public static void Main()
{
var program = new Program();
GameMenu.ShowMenu(program.UserName, DateTime.UtcNow);
}
public static void Main()
{
var program = new Program();
GameMenu.ShowMenu(program.UserName, DateTime.UtcNow);
}
You should really not be calling GameMenu.ShowMenu in the constructor.
Pobiega
Pobiega15mo ago
Yeah move all your logic out of the constructor please What you are doing is an anti pattern
Mekasu0124
Mekasu0124OP15mo ago
class Program
{
public static void Main(string[] args)
{
var user = db.LoadUser();
if (user != null)
{
UserName = user.Username;
}
else
{
user = Setup.CreateUser(db);
UserName = user.Username;
}
GameMenu.ShowMenu(UserName, DateTime.UtcNow);
}
public string UserName { get; set; }
}
class Program
{
public static void Main(string[] args)
{
var user = db.LoadUser();
if (user != null)
{
UserName = user.Username;
}
else
{
user = Setup.CreateUser(db);
UserName = user.Username;
}
GameMenu.ShowMenu(UserName, DateTime.UtcNow);
}
public string UserName { get; set; }
}
so it would be this instead? if this is how it's done, then how do I get access to Database db when I can't put it in the parameters? could I pass the database through main like this
public static void Main(string[] args, Database db)
{
}
public static void Main(string[] args, Database db)
{
}
?
public class Program
{
public static void Main(string[] args)
{
Database db = new Database();
var user = db.LoadUser();
string _userName;

if (user != null)
{
_userName = user.Username;
}
else
{
user = Setup.CreateUser(db);
_userName = user.Username;
}

GameMenu.ShowMenu(_userName, DateTime.UtcNow);
}
}
public class Program
{
public static void Main(string[] args)
{
Database db = new Database();
var user = db.LoadUser();
string _userName;

if (user != null)
{
_userName = user.Username;
}
else
{
user = Setup.CreateUser(db);
_userName = user.Username;
}

GameMenu.ShowMenu(_userName, DateTime.UtcNow);
}
}
or would it be like this? after testing, this last one i posted is a working solution. I'm not sure if it's the best way to go about it, however, it works
Want results from more Discord servers?
Add your server