Current User Global Variable C# Desktop app - c#

I know that you can use session variables in web apps, I can't figure out how to use one in a desktop (windows forms and not a mobile android) one.
I have a Player class that is used to associate players with other classes in the app/SQLDb (they may or may not be the active user). But I want to have a CurrentPlayer (the person who actually has the application running) set.
In the Program class at start up, I'm running checks to see if the current user exists and if not, add them to the SQLdb. But at that time I'd like to set up an application-wide object for the user I've just added. In fact, if they're not in the db they can't run the app.
Obviously static doesn't work because I don't want to make the Player class static all the time. But I really do need to have this object set and the info easily available. EDIT: The reason it can't be static all the time is that in every other instance but the current user, I definitely want the creation of a player object to take place. I guess it's like the old Marine Corps thing. There are many players but this one is mine.
Yes, I know, global variables are not generally good, but here it makes sense (well I think so, if you all have other ideas I'm all ears), I just can't figure out how to implement it.
EDIT: I may not be being clear here. I guess I kind of need a singleton maybe? but I don't know in which file to declare the instance or how.
I have a MYAPPPlayer class that is used generally for many many instances, it can/should not be static (unless I want to be a crappy dev). But I need a MYAPPPlayer global singleton object variable for the current user of a non-web, desktop csharp app.

In your application you should have a static User CurrentUser property.
When you log into the application, set the Current User to the instance of that user.
If you are using WPF, I would make this a dependency property and have the rest of your application's interface bind to that property. If you are using forms, you'll have to manually handle the updating of all the UI when the user changes.
Edit: Short example of how something like this could be implemented with a static running program and a static INSTANCE of an object. I would also recommend you read more about what static means, and what a class is, it might be a bit more than you think... I'll explain a bit more at the bottom
class Program
{
static Player CurrentUser;
static void Main(string[] args)
{
string username;
bool isValidUser;
//get and validate user credentials
if (isValidUser)
CurrentUser = new Player(username);
SomeMethod();
}
static void SomeMethod()
{
if (CurrentUser == null)
return;
//do stuff with user
}
}
public class Player
{
public string Name { get; private set; }
//... more properties
public Player(string name)
{
Name = name;
//... more properties
}
}
Think about static vs non-static as such..... Non static classes are the blueprints for objects that you can construct and have multiple instances of. A static class is created when you have static members in a class. All the static members are separated out and a single instance of this static class is declared and referenced throughout your entire program whenever you reference one of those static members.... a better example of what I am saying is....
class Program
{
static Person John;
static void Main()
{
Console.WriteLine("Persons who exist {0}", Person.Total);
John = new Person("John");
John.Born();
John.Birthday();
Person Jane = new Person("Jane");
Jane.Born();
Console.WriteLine("Persons who exist {0}", Person.Total);
Console.WriteLine("John's Age {0}", John.Age);
Console.WriteLine("Jane's Age {0}", Jane.Age);
Console.ReadKey(true); //Pause program
}
}
class Person
{
public static int Total { get; private set; }
public static Person()
{
Total = 0;
}
public string Name {get; private set;}
public int Age { get; private set; }
public Person(string name)
{
Name = name;
Age = 0;
}
public void Born()
{
Total++;
}
public void Birthday()
{
Age++;
}
public void Death()
{
Total--;
}
}
As you can see above I have a static main method who has access to a John Person. The Person Class is non-static, however it does have a static member. Notice that the instances of Person internally can access the static variables, but from the main method you must say Person.Total to get the total. Also note that the static part of the Person class has no access to any of the instances of Person, but all instances of Person have access to the static members of Person, this is how they can iterate up the total amount of Persons when one is born, or iterate down when one dies.

The CurrentPlayer could be static since it's the current player.
internal class Data
{
public Player CurrentPlayer { get; set; }
.... // other variables
}
Usage: Data.CurrentPlayer = ResponseFromWebServiceCall.Player;
There's nothing wrong with having a static variable to represent the current player if there can be only one current player at a time.
Edit, to clarify: If there is only to be a SINGLE representation of an object, then using a static variable to hold that information is perfectly acceptable. In your classes, it's up to you if you want to reference that player variable as I have shown above with usage, or if you want to accept the player variable through a constructor parameter, for example. Actually, doing it that way would give you the best trade-off for portability.

Related

Storing/Saving a Method and later re-calling it

What I am currently atempting to make is an inventory system. I wonder if I can store the current method and then open the inventory, and when I am done there, reopen/recall the previus method that ran.
You haven't provided very much information but I can tell you don't want to store a method, you want to store an object.
An object is an instance of a class. Depending on the kind of class you have you can either create multiple instances of a class and instantiate them multiple times across your application. Or alternatively you can create single instances of an object that you use throughout your entire application/game.
From the sounds of it, you want to use a singleton class that retains the current values of the user's inventory. So if you interact with the inventory class in one part of your program, you would like to then view and interact with the same previously modified values stored within the singleton from another part of your program.
I can't give you a concrete answer to your problem, but a possible Singleton class for your use case would look something like this;
public sealed class Inventory
{
private static readonly Inventoryinstance = new Inventory();
// Explicit static constructor to tell C# compiler
// not to mark type as before field init
static Inventory()
{
}
private Inventory()
{
// optionally, pre-populate with data stored in database when constructed
}
public static Inventory Instance
{
get
{
return instance;
}
}
public List<InventoryItem> InventoryItems { get; set; } = new List<InventoryItem>();
public void AddItemToInventory(InventoryItem item) {
InventoryItems.Add(item);
}
public void RemoveItemFromInventory(InventoryItem item) {
InventoryItems.Remove(item);
}
}
You can use this site for reference - https://csharpindepth.com/articles/singleton
If you have an application that utilises DI, you can create singleton instances that are injectable into your other app classes. This is a better way of handling singletons as they are handled by an IoC system rather than being made static for the entire application to access.

Accessing Non Static Method from another page

I have this in a toggle switch event
LevelPage.change_color() = this.ChangeColorToggle.IsOn;
I am pulling a method with the following code from another page, named LevelPage
Moving_Ellipse.Fill = new SolidColorBrush(Colors.Black);
I want the toggle switch even handler to access the method, but it would say that it needs an object for a non-static method. I am pretty new to this stuff, can anyone help me?
Static vs. Instance
class Human {
public static readonly string SpeciesName = "Homo sapiens";
private string Name { get; set; }
}
Static means belonging to a class, intrinsically. For instance, the SpeciesName of Human is "Homo sapiens". This contrasts with the non-static (or instance) property Name. A human, an instance of the Human class, can have a name. An instance of class Human with name Bob makes sense; a Human class with a static Name of Bob would be... interesting.
How to pass state between pages in C# UWP
2 recommended options: Reference
Pass data when changing from one page to another via Frame.Navigate().
Store your data statically for global access.
Personally, I prefer the second option. I usually have an object called Model that holds all of my application's persistent state. I store my only instance of Model as a static property of the App class.
For example, let's say on page1 the user must choose red or blue. Page2 will be that color. So the code would be something like:
class App : Application {
public static Model GlobalModel { get; set; }
//...
}
class Model {
public Color UserSelectedColor { get; set; }
}
class Page1 {
//...
private void StoreSelectedColor(Color selectedColor) {
App.GlobalModel.UserSelectedColor = selectedColor;
}
//...
}
class Page2 {
//...
private Color GetSelectedColor() {
return App.GlobalModel.UserSelectedColor;
}
//...
}

Why are Immutable classes not Sealed in C#

I am asking the question regarding Immutable object pattern and implementing it. I am not talking about the existing classes in .Net library like String.
I understand that immutable objects are objects which once loaded cannot be modified by any external or internal component. What if I derive the immutable class as it is not a sealed class. Then assign the object to the base class, and call a method in the base class. I have effectively changed the state of the base immutable class as its state is that of the derived class object.
public class Person
{
private readonly string name;
public Person(string myName)
{
this.name = myName;
}
public string Name
{
get { return this.name; }
}
public void DisplayName()
{
Console.WriteLine(string.Format("Person's name is {0}", this.name));
}
}
public class AnotherPerson : Person
{
private string name1;
public AnotherPerson (string myName) : base(myName)
{
this.name1 = myName;
}
}
class Program
{
static void Main(string[] args)
{
Person me = new Prasanth("MyName");
me.DisplayName();
me = new AnotherPerson("AnotherName"); ;
me.DisplayName();
Console.ReadLine();
}
}
Output :
Person's name is MyName
Person's name is AnotherName
Let's forget about the flaws of your example (the comments already said it all) and answer your question: "why are Immutable classes not Sealed in C#."
The thing is, immutability isn't a feature of the C# language. Some languages support immutability as a feature (in which case your point would be valid), but C# doesn't. In the end, you're just building an immutable class out of existing, all-purpose features. And therefore, limitations can ensue.
Also, immutability is a precaution, not a protection. The point is to prevent anybody to change the data through "normal" means. If somebody really wants to change the data, they always can, for instance through reflection (or sub-classing, as you mentioned). But if a developer does that, then there's no way he's ignoring he's mutating data that is supposed to be read-only, and we can assume he has a good reason to do so. The point of immutability is to prevent the developer from unknowingly shooting himself in the foot, not to lock him down.
You can only assign readonly string name once. I'm currently not sure if this only possible in the constructor.
You assign it in the first run "MyName" and in the second run you assing "AnotherName" to a completly different object that you created with new AnotherPerson(...)
static void Main(string[] args)
{
Person me = new Prasanth("MyName");
me.DisplayName();
// vvvvvv here you lose the reference to the old object
me = new AnotherPerson("AnotherName"); ;
me.DisplayName();
Console.ReadLine();
}

Besides constants, when would it make sense to use static/class variables In Object Oriented languages?

Is there really any good situation where it would be nice to have all objects of a class share a variable? Besides constants, of course.
there is no one answer for that. there is all sort of reasons to use and not to use. for example, a class counter the checks how many instances from this class created could be a static variable in a class. that really depends on what you are programing and why.
if you'll look here on the first answer there is also some answer for you
Static variables can be used to share a variable across all instances of a class, like in this example:
class Program
{
static void Main(string[] args)
{
//Create new instances of the Employee class
Employee joe = new Employee("joe", 1);
Employee billy = new Employee("billy", 2);
Console.WriteLine(Employee.EmployeeCount);
Console.ReadKey();
}
}
class Employee
{
public string Name { get; set; }
public int ID { get; set; }
public static int EmployeeCount { get; set; }
public Employee(string n, int id)
{
this.ID = id;
this.Name = n;
EmployeeCount++;
}
}
As opposed to static variables, instance variables allow each Employee class to have their own Name and ID variables.
The answer is Yes, there are situations you would like to use a static variable and have all instances of a class share this variable.
Example
Lets say you have a book collection. You can keep track of number of books by adding a static field of bookCount and increasing it's value when a book is created.
You can take a look at #pcnThird answer for a code example.
My favorite usage for static variables
I find static fields most effective when I want to use a field that should behave as a constant field, but I can not know it's value at compile time.
for example lets say you have a log class. you may create many instances of this log class and every instance will log to a different location on your file system.
If you want all of your logs files to have the same prefix including the date, it can not be a constant as the date has an annoying habit of changing...
The solution could be a static field (I usually prefer a static readonly which acts as a constants after the constructor has completed it's job).
Public class Log
{
public static readonly string LogFilenamePrefix;
Public Static Log()
{
Log.LogFilenamePrefix = DateTime.Today.ToString()+"_MyLogFile";
}
}
In this example you can also see that the DateTime class uses as Static Today variable, which brings me to the next example:
The obvious example
There is of course the situation of static classes where you don't have a choice but using static variables...
P.S. Some consider static variables to be evil. Take a look at this SO post.

MonoState, Singleton, or Derived Forms: Best approach for CRUD app?

I have a fairly large CRUD WinForm app that has numerous objects. Person, Enrollment, Plan, CaseNote etc. There are over 30 forms that make up the app with the UI broken down logically. Member, Enrollments, Plans, CaseNotes, etc.
I am trying to figure out how I can create my Person Object after searching on the Search Form and pass THE object to the next requested form. Whatever that may be, let's say Demographics. The short of it is that I need the Person object to be available throughout the App and there can only be one.
Now I have ZERO exposure to Design Patterns but I am trying. I have read http://www.switchonthecode.com/tutorials/csharp-tutorial-singleton-pattern and http://www.yoda.arachsys.com/csharp/singleton.html but I want to make sure I understand correctly how to apply this to my situation.
First, the examples state that you are accessing a reference, correct? Am I mistaken or would I need to access the value?
Second, is there anything else that I need to do to make this Globally available? Do I just declare a instance on each form but through this Singleton Pattern so as to not have more then one?
Thanks
EDIT 1
To clarify, All objects are child objects of Person. Also, As the Search Page eludes to; the users can select a different currentPerson. But they can only interact with ONE Person at a time.
Lastly, as I stated I am an infant in this and if I should be considering something else, a different approach please say so and if you'd be so kind as to offer some explanation as to why, I'd be very grateful.
EDIT 2
Based on Medicine Man's comment I thought I wauld clarify.
First, Thank you to everyone who has contributed so far.
Second, I don't know the first thing about design patterns and I certainly don't have the foggiest if a certain one is needed in my current situation.
If someone has a better, simpler, or ,in your opinion, a more fitting method of passing a Data Object from FORM to FORM to FORM then PLEASE tell.
In the end I just need a way of tracking the information as my users go from place to place.
Thank You
First, the examples state that you are accessing a reference, correct? Am I mistaken or would I need to access the value?
Your class that you are accessing is a reference to a single class in memory. For example, say your class is:
public class Person { ... }
If you have a singleton of that, you'll have a single "Person" saved in memory, with a shared reference to that one person in the singleton. When you access your single person, you'll be working with that reference, which is probably what you want. Any changes to the person will change it everywhere.
Second, is there anything else that I need to do to make this Globally available? Do I just declare a instance on each form but through this Singleton Pattern so as to not have more then one?
Singletons are used to basically enforce that every time you use the object, it's the same object (each use is a separate reference to the one, single object in memory). You can just grab the singleton anywhere you need it, and it'll just work.
You can use the Singleton pattern to assure that only one instance is ever created.
However, the jury is still out (at least in my mind) on whether this is a good decision. There's plenty of reading on SO and other places about this.
I would approach this from a different angle. I'd make all of my forms take in a Person instance in the constructor. That way, each form is only ever worried about it's instance of Person.
You could do this by creating a new class that inherits from Form and has a field/property/constructor for your Person. Then, any form that uses Person can inherit from your new class.
You would, of course, have to manage the creation of your Person object. You could even do this with a singleton. However, the benefit is that each form doesn't have to know how to create a Person or who created the Person. That way, if you choose to move away from the Singleton pattern, you wouldn't have to go change all of your references to your singleton instance.
EDIT:
Here's some code to demonstrate this. It took me a while to get the designer to play nice. I had to add an empty private constructor in PersonForm to get the designer to not throw an error.
Program.cs
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyDerivedForm(new Person { Name = "Hello World!" }));
}
}
Person.cs
public class Person
{
public virtual string Name { get; set; }
}
PersonForm.cs
using System;
using System.Windows.Forms;
public class PersonForm : Form
{
private readonly Person myPerson;
protected virtual Person MyPerson
{
get
{
return this.myPerson;
}
}
private PersonForm()
{
}
public PersonForm(Person person)
{
this.myPerson = person;
}
}
MyDerivedForm.cs (add a label named label1)
public partial class MyDerivedForm : SingletonMadness.PersonForm
{
public MyDerivedForm(Person person)
: base(person)
{
InitializeComponent();
}
private void MyDerivedForm_Load(object sender, EventArgs e)
{
label1.Text = this.MyPerson.Name;
}
}
You could do something like this:
public static class PersonController
{
private static Person _Person;
public static Person GetPerson()
{
if (_Person == null)
_Person = new Person();
return _Person;
}
}
This will ensure there is only one person object. You will be getting a reference to the _Person object, not a copy, so any changes will be to the single object you're expecting.
As Reed says, singletons enforce that the same object is used throughout the application. However, from your question it doesn't look to me like you do have the same instance of the person class available throughout the entire application, since there is the "search form" which looks like it allows you to change the currently selected person.
In this case your singleton may need to be a container class that holds the current context of the application and which person is currently selected. This may be something like:
public class Context
{
private static Context _instance;
public static Context Instance
{
get
{
if (_instance == null)
{
_instance = new Context();
}
return _instance;
}
}
public Person CurrentlySelectedPerson { get; set; }
private Context() { }
}
(Note that this isn't an ideal singleton pattern since it isn't thread safe...)
Then the search form would set the currently selected person with:
Context.Instance.CurrentlySelectedPerson = personSelectedInForm;
And the demographic from can use it like:
//Get the demographics for the current person
ShowDemographics(Context.Instance.CurrentlySelectedPerson);
You could also use the monostate pattern with your Personclass.
public class Person
{
public Guid Id { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
}
Build a monostate object for Person.
public class CurrentPerson
{
public static Person Person { get; set; }
public Guid Id
{
get { return CurrentPerson.Person.Id; }
set { CurrentPerson.Person.Id = value; }
}
public String FirstName
{
get { return CurrentPerson.Person.FirstName; }
set { CurrentPerson.Person.FirstName = value; }
}
public String LastName
{
get { return CurrentPerson.Person.LastName; }
set { CurrentPerson.Person.LastName = value; }
}
}
Now you can initialize the monostate.
CurrentPerson.Person = GetPersonByUserInput();
And then use CurrentPerson instances throughout the code and they will all access a common shared state.
CurrentPerson currentPerson = new CurrentPerson();

Categories