How to consume List from another class - c#

Whenever I give new when instantiating a class or list, will it be recreated? I'm having trouble consuming a list that I fed into another class.
I'll give an example of my question to make it clearer:
I have the Customers class:
public class Customers
{
public int id { get; set; }
public string name { get; set; }
}
and I have another class called:
public class CustomerList
{
public List<Customers> dataCustomers;
}
these two are inside the same file or better same namespace.
Now I will feed this list through another Form1, so first I will instantiate it in this new form1:
CustomerList listCustomers = new CustomerList();
Now I'm going to feed the data into the class:
Customers customer = new Customers()
{
id = 1,
name = "Matthew"
}
and finally I will add the records inside the list:
listCustomer.dataCustomers.Add(customer);
Now I want to consume this list from another form/class, but I don't know how to do it. I tried instantiating it again in this new class. but it always returns saying that dataCustomers was null, saying that the object is not being referenced. so well I couldn't understand this concept well, how to consume a list that I fed into another form/class.
In this form that I want to consume, I did it like this, I instantiated it:
CustomerList objCliente = new CustomerList();
and to test, I tried to play inside a message box, just to see the result.
MessageBox.Show(objCliente.dataCustomers.ToString());

Make your property to be static, so that it can be accessed anywhere.
public class CustomerList
{
static public List<Customers> dataCustomers;
}
The way to add new customer now become like this :
CustomerList.dataCustomers.Add(customer);
and to access it also same. You can access it using this way :
CustomerList.dataCustomers

Related

How to create a static array from objects in controller (ASP.NET MVC) without overwriting every time

I have an ASP.NET MVC web application. In the HomeController, I want to create an array of objects of the class I need, so that when new objects are written to this array, it would not be overwritten, but added as new elements to itself.
For example: this is a piece of code from HomeController. Here I create a static array of objects so that we can access it without creating a class object.
// ...
public static List<Person> personMessages { get; set; }
public HomeController()
{
personMessages = new List<Person>();
}
// ...
And this is the code from another class, in which I add new objects to this array (personMessages).
HomeController.personMessages.Add(personObj);
Console.WriteLine("Array count: " + HomeController.personMessages.Count);
When my application is running, after each addition of a new object, the length of the array will always be 1 and it will contain the last added object.
How to solve my problem and create something like a data repository (based on my array of objects personMessages)?
This is really bad to have personMessages as a member of the controller class. and you are accessing it using the controller class. It violates the single responsibility principle as well.
you should create a repository class and have a static member of it. you can create a method to add an item to the list.
public static class PersonRepository
{
public static List<Person> personMessages { get; set; } = new List<Person>();
public static void AddPerson(Person person)
{
personMessages.Add(person);
}
}
you can call the method like this PersonRepository.AddPerson(personObj);
As a suggestion, I think you should use some logging instead of Console.WriteLine as it's not a console application.

Access Class in Class from another Script?

first of all I'm a rookie in Unity3D and especally in programming. At this moment i try diffrent things and study different documentations to create an economy simulation game.
So please be merciful to me if i dont understand your solutions instantly ;)
I need to access a twodimensional List from another script.
In Script1 I use a Class to make the 2D
public class OrderArray : MonoBehaviour
{
List<Order> orders;
public class Order
{
public string company{ get; set; }
public string date{ get; set; }
public int quantity{ get; set; }
public string deliverdate{ get; set; }
}
void Start()
{
orders= new List<Order>();
orders.Add(new Order
{ company = "Woodpecker Corp",
date = "21.11.2014",
quantity= 250,
deliverdate= "29.11.2014" });
// To access the Data in the list Im using:
Order order1= orders[0];;
Debug.Log(order1.company)
}
So far so good. Script1 runs good for me.
Now how can I access "order1.company" for example from a different Script on the same GameObject?
I knwo how I can access the variable in Script1 und Class Script in generall but I cant make it to accsess the variables in class "Order".
My result of Script2 till now
public class menu : MonoBehaviour
{
OrderArray orderarray;
Orderarray.Order orderclass;
void start()
{
orderarray= gameObject.GetComponent<OrderArray>();
}
Now I have access to the class OrderArray but I dont know how can i access the class Order inside OrderArray.
Maybe you could give me an approuch to solution or an example code I can transfer for my problem. Thank you.
You can extend your OrderArray with a GetOrderByIndex method:
public Order GetOrderByIndex(int index){
return orders[index];
}
You could use it in your start like this:
void start()
{
orderarray= gameObject.GetComponent<OrderArray>();
Order order1 = orderarray.GetOrderByIndex(0);
//do what you want with order1
}
Doing something like Mark Smit mentioned is probably best. One thing you should consider though is making "Order" a struct instead of a class since it doesn't hold a whole lot of data and you'll have a bunch of them I'd imagine. For further information take a look at this. And add a constructor to "Order" for easier creation of a new one ->
new Order("Woodpecker Corp", "21.11.2014", 250, "29.11.2014")

Accessing a property in one ViewModel from another

I want main viewmodel to have a certain list, and then access from many other viewmodels.
For example, in MainViewModel.cs I will have a list of 50 numbers,
then in NumListViewModel.cs, I'd like to access it in order to show it as a list, and in AddNumViewModel.cs I'd like to be able to update that list.
It's been suggested that I use events / evenaggerator, which I did, but unfortunately, for all I know all I can do with it is send a num from one view to another and tell it to update the list, but the problem is, as the program grows, I will need to have a lot of subscribers in the main view model, and when something actually happens I will have to "publish" events according to the number of subscribers which makes it even harder to maintain.
I also found another answer, instructing to create an instance of anotherVM within the mainVM, with a parameter set to "this" which is a reference to the mainVM.
It works, but then again, it could get quite long.
So my question is, is there a better way to access a property from another VM?
Like literally have the an instance of the class that holds the list in the mainVM, and then just be able to update / access it from the other VMs, without having to explicitly program which VM can. Would make life so much easier.
In your answer, please try to avoid suggesting frameworks.
Although there are some really good ones, I want to be able to do at least that by myself.
For example:
MainVM.cs:
public class MainVM
{
List lst = new List(); //Let's just say it's full...
}
OtherVM.cs:
public class OtherVM
{
lst.Add(3);
}
PS: Yes I know it has been asked already, and yes I have done my research, BUT I the answers I found are too 'static', I guess?
If you want direct access to the list from an external ViewModel, then your options are to:
Pass the List to the OtherVM as a constructor argument or public property. Then the OtherVM can treat it like a member.
Pass the MainVM to the OtherVM as a constructor argument or public property. Then the OtherVM can access the List by first accessing the MainVM.
Example:
public class MainVM
{
public List<XX> MyList { get; set; }
}
public class OtherVM
{
public MainVM TheMainVM { get; set; }
public OtherVM(MainVM theMainVM)
{
TheMainVM = theMainVM;
// Access the MainVM's list
TheMainVM.MyList.Add(stuff);
}
}
Give the MainVM a static property called "Default" or "Instance," so you can access the static instance of MainVM from within OtherVM, without assigning it as a member field.
Example:
public class MainVM
{
private static MainVM _instance = new MainVM();
public static MainVM Instance { get { return _instance; } }
public List<XX> MyList { get; set; }
//other stuff here
}
//From within OtherVM:
MainVM.Instance.MyList.Add(stuff);

class variable gets reset when calling methods in multiple forms

Updated to reflect to my own source
I'm in process of building my first winform application in c# and I'm trying to figure out the best practice for structuring my classes to work smoothly when I use them in my forms.
I have a couple of examples which I will try to explain the best way i can.
When working with get/set variables in a class, the best practice should be something like this:
JobMove.cs
public class JobMove
{
private List<string> jobNames { get; set; }
public string Scanner;
public JobMove()
{
this.Scanner = Properties.Settings.Default.Scanner;
}
public void ListSelected(ListBox lbx)
{
foreach (string jName in this.jobNames)
{
lbx.Items.Add(jName);
}
}
public static List<string> GetCheckedJobs(ListView lw)
{
int countChecked = lw.CheckedItems.Count;
int itemCount = 0;
List<string> jList = new List<string>();
foreach (ListViewItem item in lw.CheckedItems)
{
JobInfo jobInfo = Job.Find(Convert.ToInt32(lw.Items[item.Index].SubItems[1].Text));
jList.Add(jobInfo.Name);
itemCount++;
}
return jList;
}
}
My problem is when I combine this with my forms and I call this, then I would try to do something like this:
MyForm1.cs
public partial class MyForm1 : Form
{
private void btnMoveJobs_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Scanner = cbxScanners.SelectedItem.ToString();
JobMove moveJobs = new JobMove();
frmMoveJobs FrmMoveJobs = new frmMoveJobs();
FrmMoveJobs.ShowDialog();
}
}
MyForm2.cs
public partial class frmMoveJobs : Form
{
public frmMoveJobs()
{
InitializeComponent();
JobMove moveJobs = new JobMove();
lblFrom.Text = moveJobs.Scanner;
moveJobs.ListSelected(lbxJobsToMove);
cbxMjScanners.DataSource = System.Enum.GetValues(typeof(Scanners));
}
}
But when I call MyClass in MyForm2 and I want to call the DoSomethingElse method, then myString will be reset to a null value. And that makes sense to me, but how do I work around this?
I tried to figure out what to use here to get easier around these flaws in my code, but my knowledge is far too weak to just implement an easy solution.
I know I could just store this variable in Settings.settings as an example, but to me that just seems like a real overload for such a simple task.
I might just need a point in the right direction to right on what to do in this situation.
If you do a MyClass myClass = new MyClass(); then indeed - the values are independent and unrelated. If you want to share the MyClass instance then pass the MyClass instance between the forms. Perhaps:
using(var form2 = new Form2()) {
form2.SensibleName = existingMyClassInstance;
form2.ShowDialog();
}
(note the using above btw; when using ShowDialog() it is your job to make sure the form is disposed; it only gets disposed automatically if using Show())
Firstly, they're properties, not variables (the variables are the underlying data source).
Secondly, the whole point of get/set accessors is so you can get and set the value without needing helper methods.
Thirdly, and as to your problem, you're creating a new instance of the class in each form (hinted at by the new keyword) and the value of the property will be whatever it is initialised as on construction of the instance (or not.) i.e. the values of properties are not shared between different instances of the same type.
Think of the mold for a key: I can get multiple instances of the key cut from a "blueprint", but any damage that one suffers won't be reflected by the rest - they're unique in that sense.
If you want the forms to both access the same instance of that type, then you will need to stash the instance somewhere in your code which is accessible to both.
A few options:
Pass in an instance of MyClass in the form2's constructor.
Make MyClass a static property of either Form1 or Form2 and access it via that on the other form.
Make MyClass static (not recommended).
If you want to use the instance of MyClass created in MyForm1 inside of MyForm2, you need to provide it to MyForm2.
Something like this would work:
public partial class MyForm2 : Form
{
public MyForm2(MyClass given)
{
InitializeComponent();
given.DoSomethingElse();
}
}
Easy Solution:
private static string myString { get; set; }
Why: because you initialize the class again when initializing Form2 and it will create a new class. With the "static" keyword you create a property which is the same in all instances of this class.
BUT: please read some books before continuing, this would be the solution to this problem, but the source of many others. Try to understand C# and Forms first, than (or alongside with reading/learning) start coding!
this is because each of your form has a new object of "MyClass".
To achieve what you want to do use a static property... this won't be initialized and gives back the same value for each object of MyClass
it looks like this
public class MyClass {
public static string myString { get; set; }
public void ChangeMyString(string newString)
{
myString = newString;
}
public void DoSomethingElse()
{
MessageBox.Show(myString);
}
}

Why objects are orphan, when creator exist

Consider following code
public class City
{
public string Name { get { return "New York"; } }
Building empEstate;
Building nyTimes;
public void Init()
{
// I hate passing "this" to all object
empEstate = new EmpEstate(this);
setSomeProperty(empEstate);
// any one can create new object of some other city
// and pass to the building
nyTimes = new NYTimes(this);
...
other = new OtherBuildings(this)
}
public void PrintAddresses()
{
empEstate.Print();
nyTimes.Print();
...
other.Print();
}
}
public abstract class Building {
City _city;
public Building(City city){
this._city = city;
}
public abstract string Name { get;}
public void Print(){
Console.WriteLine(this.Name);
Console.Write(",");
Console.WriteLine(this._city.Name);
}
}
First thing I want better solution to this approach. Print is just an example. Actually each building object raise some event to City object. I don't want to add handler to each building as there could be several buildings in city. Also I do not want to add each of them into list, as it is two task for each building (one initialization and second add to list, one forget to add to list when writing new building). For this, I want caller to be automatically available to callee, like Parent property of control (though it was added to this.Controls)
Using memory, can we know who is the parent of current object. How does GC knows that object is not being referenced (including creator). Can't we create a method (safe or unsafe) using memory to identify the caller object. I see we can use StackTrace to see the call hirarchy, can we intercept here when a new object is being created.
Building factory on city solved my problem of passing this to each object
public interface ICity
{
string Name { get; }
}
public abstract class City : ICity
{
public T CreateBuilding<T>()
{
T buildingInstance = Activator.CreateInstance<T>();
((IBuilding)buildingInstance).SetCity(this);
return buildingInstance;
}
public abstract string Name { get; }
}
interface IBuilding
{
ICity City { get; }
void SetCity(ICity city);
}
public abstract class Building : IBuilding
{
private ICity _city;
public ICity City { get { return _city; } }
public void IBuilding.SetCity(ICity city)
{
this._city = city;
}
public abstract string Name { get; }
public void Print()
{
Console.WriteLine(this.Name);
Console.Write(",");
Console.WriteLine(this._city.Name);
}
}
public class EmpEstate : Building
{
public override string Name { get { return "Emp State"; } }
}
public class NYTimes : Building
{
public override string Name { get { return "NY Times"; } }
}
public class NewYorkCity : City
{
public override string Name { get { return "New York"; } }
EmpEstate empEstate;
NYTimes nyTimes;
public void Init()
{
// Now I dont need to pass this
empEstate = this.CreateBuilding<EmpEstate>();
setSomeProperty(empEstate);
// now any one cannot create building in new your and
// say it belongs to Philedelphia :)
nyTimes = this.CreateBuilding<NYTimes>();
}
public void PrintAddresses()
{
empEstate.Print();
nyTimes.Print();
}
}
Problem was there were several classes already created and for new functionality we needed the creator object in the base class of Building Object. We did not wanted to modify the constructor of each class and pass this object to each. And City class (in example) was basically code on plugin side, so allowing them to pass city (if plugin developer pass wrong city) may disturb the functionality of entire app. So modifying the plugin base solved my purpose. Suggestions are welcome.
There is no logical "owner" of an object. Inspecting the stack trace is... not usually ideal. By comparison to Parent, that is not very different to your existing approach - merely that is set via methods/properties rather than in the constructor.
If the city is only necessary for the context of methods like Print, why not pass it in as a parameter, i.e. nyTimes.Print(this) etc. If you might need other values, rather than taking lots of parameters, consider using some kind of context object that has a city - i.e.
class PrintContext {
public City City {get;private set;}
// other stuff...
public PrintContext(City city/*, other stuff...*/) {
City = city;
}
}
I think you are misusing the terms parent and creator. The object that created the instance has no special relationship with the instance (e.g. factories create objects, but do not maintain references to them), so, in general, there is no way to find out who or what created a concrete instance.
In the same sense, parent has no meaning on a general object. We can somehow infer that the Form is parent to the TextBox, but that is not a special relationship. It this case it just means that the TextBox is in the form's Contols collection, and that it's Parent is set to the Form.
You are right that this could potentially lead to inconsistencies (Form1 thinks that TextBox is it's child, but the TextBox thinks that it's Parent is Form2), but I do not know of, and don't think there is a better solution of this kind of relationship than the Children collection / Parent reference.
Picking a few of your many questions:
I hate passing this
Why? You are telling the building which city it belongs to. How else could you do this. I see that as a common idiom for wiring objects together.
Also I do not want to add each of them into list, as it is two task
for each building (one initialization and second add to list, one
forget to add to list when writing new building).
I'm not clear what list you want to add them to, but your concern about "forgetting" is overcome if you do the work in the base constructor:
public Building(City city){
this._city = city;
// add the building to the list here - nothing to "forget"
}
As for GC, once a creator has created something there is no relationship between them unless you choose to retain a reference. You have done that with
empEstate = new EmpEstate(this);
so as long as the City is not a candidate for garbage collectio then the EmpState won't be either.

Categories