Can't access data through multiple class layers [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
For my Project I have to build a data structure to represent an xml file.
My Idea was to use multiple classes representing the different xml layers.
My problem now is how can I change data in the lowest layer from the uppermost one.
In my code example are three calls 2 work 1 doesn't. Why doesn't the last one work?
Is there another way of organizing the data?
public class option
{
public string optionID;
public void setoptionID(string text)
{
optionID = text;
}
}
public class module
{
public option[] opt = new option[1];
private string moduleID;
public void setmoduleID(string text)
{
moduleID = text;
}
}
public class catalogitem
{
public module[] modul = new module[1];
private string ShortName;
public void setShortName(string text)
{
ShortName = text;
}
}
public class Katalog
{
private catalogitem[] items = new catalogitem[1];
public Katalog()
{
}
public void setcatalogitems()
{
items[0].setShortName("asdf"); //works
catalogitem.modul[0].setmoduleID("5"); //works
items[0].modul[0].setmoduleID("5"); //doesn't work
}
}

For me, none of the three statement work.
You have to initialize the objects itself, not only the array.
items[0] = new catalogitem();
items[0].setShortName("asdf");
items[0].modul[0] = new module();
items[0].modul[0].setmoduleID("5");
But I would also suggest you, to use properties instead of setShortName() / setmoduleID() in your classes and methods for adding and initializing sub items.
Of course it depends on the specification / your intention (that I don't know), but here is a possible way to implement for example
CatalogItem. You can read/write ShortName and enumerate all existing modules. I would take a list, not an array. Modules can be
only added one by one and you can check them before really adding them:
public class CatalogItem
{
private readonly List<Module> mModuls;
public IEnumerable<Module> Moduls
{
get { return mModuls; }
}
public string ShortName { get; set; }
public CatalogItem()
{
mModuls = new List<Module>();
}
public void AddModule(Module module)
{
// Add a check that module is assigned.
mModuls.Add(module);
}
}

Some suggestions
Use properties instead of Set Methods
Write only properties are not good by design
if you need only one object of a type, create the object instead of array with 1 object
follow naming conventions C# Coding Conventions and Naming Guidelines
Your somewhat updated code is below.
public class Option
{
public string OptionID { get; set;}
}
public class Module
{
// if you need only one Option, why not create one public Option object, instead of an Array
public Option Option = new Option();
public string ModuleID { get; set; }
}
public class CatalogItem
{
public Module Module = new Module();
public string ShortName { get; set; }
}
public class Katalog
{
private List<CatalogItem> items = new List<CatalogItem>();
public Katalog()
{
for(int i = 0; i < 10; i++)
items.Add(new CatalogItem());
}
public void SetCatalogItem()
{
foreach(CatalogItem ci in items)
{
ci.ShortName = "asdf";
ci.Module.ModuleID = "5";
}
}
}
Glad to help! Please remember to accept the answer if you found it helpful.

Related

Reference known property in (List<someClass>)someObject

have tried some searches. Probably my lack of knowledge that I'm not using the right search terms or perhaps just not understanding the answers.
I have a method that is being passed an object, which I want to output a particular value to a text file.
I already know the object will be a List< someClass > of a few different possible classes (customers/employees/items etc). But all of the classes contain the same string property (e.g.) string idNumber.
So something like this:
public static void OutputFile(object myInput)
{
foreach (someGenericObject in (List<anyType>)myInput)
{
string textToOutput = someGenericObject.idNUmber;
//output the text to somewhere else here
}
}
I feel like as long as I know that it will always contain a this "idNumber" property regardless of the type, that I should be able to reference it somehow. But I just can't seem to get my head around it?
The error I typically get is something like:
Cannot cast List< Employee > to List< object > etc.
Thanks in advance
As I suggested in the comments, if you have the ability to modify these classes, you can have them all inherit from an interface IHasIdNumber with an idNumber property.
Your method would then become:
public static void OutputFile(IEnumerable<IHasIdNumber> myInput)
{
foreach (var item in myInput)
{
string textToOutput = item.idNUmber;
//output the text to somewhere else here
}
}
There are a few ways you can solve this.
Recommended way: Implement common interface:
public interface INumberable { // I'm sure you can come up with a better name...
string IDNumber { get; set; }
}
And then all the possible classes that can be passed into the method will implement INumberable. Your method can then look like this:
public static void OutputFile(List<INumerable> myInput)
{
foreach (var someGenericObject in myInput)
{
string textToOutput = someGenericObject.idNUmber;
//output the text to somewhere else here
}
}
Not-so-recommended way: Reflection:
Type t = someGenericObject.GetType();
var p = t.GetProperty("idNumber");
string theStringYouWant = (string)p.GetValue(someGenericObject);
Note that this is not very safe.
You can use [dynamic].
foreach (var someGenericObject in (dynamic)myInput)
{
//...
}
If all your classes have the same property you want to access in foreach loop you can do in via interface.
public interface ISmth {
int MyProperty { get; set; }
}
public class Student : ISmth {
public int MyProperty { get; set; }
}
public class Employee : ISmth {
public int MyProperty { get; set; }
}
public static void DoSmth(object myObj) {
foreach(ISmth item in (List<object>)myObj) {
Console.Write(item.MyProperty);
}
}
List<Student> stdList = new List<Student>();
DoSmth(stdList.Cast<object>().ToList());

I want to fill class members with default if they are missing, using generic in C#

I have multiple web requests that post JSON object and I have serializable classes with all the fields. For example:
[Serializable]
public class RequestOne()
{
public string date;
public string information;
public string subject;
}
[Serializable]
public class RequestTwo()
{
public int ID;
public string Data;
public string message;
}
And my method takes partially filled request class and I want to fill in any missing fields with default values declared in constant class.
And I want to avoid writing each method with for each request, like :
public static void FillWithDefault(this RequestOne request)
{ if (request.date.Equals(null)) request.date = DEFAULT_DATE;
if (request.information.Equals(null)) request.information = DEFAULT_INFO;
if (request.subject.Equals(null)) request.subject = DEFAULT_SUBJECT;
}
public static void FillWithDefault(this RequestTwo request)
{
//do the same for the fields in RequestTwo
}
I want to know if there is any way to achieve this using generic?
I want to do something similar to this:
public static void FillWithDefault<T>(this T request)
{
if(typeof(T) == typeof(request))
{
//check each member in request and fill with default if it's null
}
.
.
.
}
So that in my main method I can use like this :
RequestOne request = new RequestOne();
request.FillWithDefault();
RequestTwo request2 = new RequestTwo();
request2.FillWithDefault();
Can someone please help with idea on this? Am I overthinking on this? I'm new to generic so please feel free to advise on my code.
Edit
Sorry guys, I did not mention that I will be using this method for test automation. Those request contracts cannot be changed since it's by design. Sorry again for the confusion!
Use constructors. Also make use of properties. Don't gather the default filling code to one place, it's the responsibility of the classes so keep them there.
[Serializable]
public class RequestOne()
{
public string date { get; set; };
public string information { get; set; };
public string subject { get; set; };
public RequestOne()
{
Date = DEFAULT_DATE;
Information = DEFAULT_DATE;
Subject = DEFAULT_SUBJECT;
}
}
[Serializable]
public class RequestTwo()
{
public int ID { get; set; };
public string Data { get; set; };
public string Message { get; set; };
public RequestTwo()
{
Data = DEFAULT_DATA;
message = DEFAULT_MESSAGE;
}
}
Generics are used when the types have common operations/properties defined so you can apply the same routine for each type in one place instead of declaring different methods for each type.
However in this case, you have two different types with different properties, so I would not use generics here. You can achieve it with manual type checking and using reflection to get properties and set them but it's not a good way and definitely wouldn't be a good usage of generics.
Overloading is the way to go.
you can use property
[Serializable]
public class RequestOne()
{
private string _date;
public string date { get { return _date;} set { _date = value ?? DEFAULT_DATE; }};
public string information; // same here
public string subject; //same here
}

(C#) Access/Modify Objects in a List

New here, I've been learning c# for about a month.
Anyway, I've been searching StackOverflow for a couple of days now and couldn't find a specific answer to my problem...
//Here's my Class
public class Guy
{
public static int ID { get; set; }
public static int LifeExpectancy { get; set; }
public static bool Living { get; set; }
public Guy(int id, int lifeExpectancy, bool living)
{
ID = id;
LifeExpectancy = lifeExpectancy;
Living = living;
}
}
What I'm trying to do is create a specific number of "someGuy" objects to then put them into a public list using this method...
public static List<Guy> Guys = new List<Guy>();
public static void makeSomeGuys(int howManyGuys)
{
for (int i = 0, i <= howManyGuys; i++)
{
int id = i;
int lifeExpectancy = 80;
bool alive = true;
Guys.Add(New Guy(id, lifeExpectancy, alive));
Console.WriteLine("Made a new Guy {0}", id);
}
return;
}
Questions in order of importance:
How do I access a specific object as well as its parameters? (Accessing from the list "Guys".)
How do I access an object from this list in another class? (Not that I absolutely need to, I'm curious)
Can I search for an object in a list by using its parameters? (As opposed to doing something like... humanPopulation[number])
Should I create a new list for objects that have had their parameters modified? (As opposed to leaving it in the original list)
Is it possible to remove items from a list? (Just in general, is that a thing people do? if so, why?)
I really only need the first question answered. The rest of them are just a bonus. Thanks!
First you need to remove the static modifier from the properties of the Guy class, i.e.:
public int ID { get; set; }
public int LifeExpectancy { get; set; }
public bool Living { get; set; }
because static causes the property to be an attribute of the class itself, rather than the instances of the class (the individual 'guys').
To access life expectancy of the first guy (the zeroth):
Console.WriteLine(Guys[0].LifeExpectancy);
To access life expectancy of the fifth guy:
Console.WriteLine(Guys[4].LifeExpectancy);
using System;
using System.Collections.Generic;
using System.Linq;
namespace test
{
public class Guy
{
private int m_ID;
private int m_LifeExpectancy;
private bool m_Living;
public int ID
{
get { return m_ID; }
set { m_ID = value; }
}
public int LifeExpectancy
{
get { return m_LifeExpectancy; }
set { m_LifeExpectancy = value; }
}
public bool Living
{
get { return m_Living; }
set { m_Living = value; }
}
public Guy(int id, int lifeExpectancy, bool living)
{
ID = id;
LifeExpectancy = lifeExpectancy;
Living = living;
}
}
public class MyFactory
{
public IList<Guy> MakeSomeGuys(int howManyGuys)
{
IList<Guy> localGuys = new List<Guy>();
for (int i = 0; i <= howManyGuys; i++)
{
int id = i;
int lifeExpectancy = 80;
bool alive = true;
localGuys.Add(new Guy(id, lifeExpectancy, alive));
Console.WriteLine("Made a new Guy {0}", id);
}
return localGuys;
}
}
public class program
{
public void Main()
{
MyFactory mf = new MyFactory();
IList<Guy> guys = mf.MakeSomeGuys(5);
//How do I access a specific object as well as its parameters? (Accessing from the list "Guys".)
int GetFirstGuyId = guys.FirstOrDefault().ID; //LEARN LINQ
//How do I access an object from this list in another class? (Not that I absolutely need to, I'm curious)
//you need to learn about object oriented encapsulation for better understanding.
//Can I search for an object in a list by using its parameters? (As opposed to doing something like...humanPopulation[number])
Guy guyById = guys.Where(g => g.ID == 5).FirstOrDefault(); // returns the first match (need to learn lambda expression)
//Should I create a new list for objects that have had their parameters modified? (As opposed to leaving it in the original list)
// you need to learn about passing values by value / reference (by reference you already changing the original!).
//Is it possible to remove items from a list? (Just in general, is that a thing people do? if so, why?)
//yes
guys.Remove(guyById);
}
}
}
You're likely new to C# and OO programming, so I've included some good links in this answer.
Regarding question 1 only:
Firstly, your Guy class properties aren't properly encapsulated. Make sure you properly scope the ID, LifeExpectancy and Living properties like shown in this article.
If you'd like to access a specific item, that is, a Guy with a particular ID, you'd be better off using an associative container like Dictionary.
If you're happy with the List container, you need to use the Find method on Guys as shown in the example at the link. You'll notice the term Predicate in the documentation, this link will elaborate.

array of pointers to objects in another class [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have to create class like DataBase that will contain menu, adding users, editing them, deleting etc.
Users are from class User.
It looks like:
class base
{
protected int mAccounts=0;
protected const int mMaxAccs=10;
osoba[] list = new osoba[mMaxAccs];
public void menu(){...}
public void add()
{
user user1("Jurand","ze Spychowa",15231512,"1410-10-26","hue#x.com");
mAccounts++;
}
... useless code there
}
then there is User class
class user
{
private string mName;
private string mSurname;
private int mPesel;
private DateTime mBDate;
private string mEmail;
osoba(string mName2, string mSurname2, string mPesel2, string mBDate2, string mEmail2)
{
mName = mName2;
mSurname = mSurname2;
mPesel = Convert.ToInt32(mPesel2);
mBDate = Convert.ToDateTime(mBDate2);
mEmail = mEmail2;
}
The problem is adding new accounts. I totally don't know how to make it working
So the users will be stored in base class and you will have access to edit and add them etc.
Anyone know how to make it working (Creating objects properly)?
I suggest adding properties to User class:
class User
{
public string mName { get; private set; }
public string mSurname { get; private set; }
public int mPesel { get; private set; }
public DateTime mBDate { get; private set; }
public string mEmail { get; private set; }
//constructor for User class
public User(string mName2, string mSurname2, string mPesel2, string mBDate2, string mEmail2)
{
mName = mName2;
mSurname = mSurname2;
mPesel = Convert.ToInt32(mPesel2);
mBDate = Convert.ToDateTime(mBDate2);
mEmail = mEmail2;
}
}
and modify your add method (also changed object where you store data from array to List):
class MyDB
{
List<User> list = new List<User>();
public void add()
{
//use constructor to create new object
User person = new User("Jurand", "ze Spychowa","15231512","1410-10-26","hue#dupa.com");
//add object to list
list.Add(person);
}
}
Its not good idea to mix different languages in code so try avoiding naming objects/methods like "osoba".
You will probably benefit from reading following articles (in Polish):
C# Constructors
C# Properties
I belive that only thing that is missing in your add() method is:
osoba[mAccounts] = user1;
before mAccounts++ line.
Make fields public only if your User class is going to be stupid data object which only store data and contain no methods (maybe except formatting, converting etc.).

How to create a property for a List<T>

private List<T> newList;
public List<T> NewList
{
get{return newList;}
set{newList = value;}
}
I want to create something like this, but this is won't work. it's just an example to demonstrate my goal as it's pretty common creating proprties for string and int and even T but I've never seen a List property
Is it even possible do such a thing, creating a property for type List ?
EDIT
I have a normal class that has normal properties (string properties, int properties, etc) but I have this property that stores user options, So on the presentation layer I had to convert them into a string so I could be able to store them in the Object. Now is it possible to have a property of type List to store the multivalues in a better and clean way, instead of converting information into one string and then split it and again join it! Thanks Again =D
EDIT2
private List<KeyValuePair<string, string>> _settings;
public List<KeyValuePair<string, string>> MySettings
{
get { return _settings; }
set { _settings = value; }
}
I used the exact code you posted but the property still won't appear in the object's instance, so I tried adding code in the get and set (I wonder why you left them empty or does it means something?) and also added a private variable in the class but still it doesn't appear in the properties of the object's instance!
I hope you could provide the exact code to implement this property and a simple code that assigns or retrieves from/to an instance of this class object
It's the first time to even hear about this KeyValuePair and all the tutorials are pretty simple and not for my case, sorry!
The Last Edit: After a lot of researching and the help of Mark Avenius I found the perfect answer. hope everyone can benefit from this.
NOW! HOW TO CREATE A PROPERTY FOR A LIST :
The Options Class
Public Class Options
{
private string id;
private int option;
public int ID
{
get { return id; }
set { id= value; }
}
public string Option
{
get { return option; }
set { option = value; }
}
}
The Users Class
public class Users
{
private int userId;
private string pass;
private List<Options> userOptions = new List<Options>();
public int ID
{
get { return userId; }
set { user = userId; }
}
public string Pass
{
get { return pass; }
set { pass = value; }
}
public List<Options> OptionsList
{
get { return userOptions; }
set { userOptions = value; }
}
}
The Presentation Layer
Users newUser = new Users ();
Options userOption = new Options ();
userOption.ID = int.Parse(txtBxID.Text);
userOption.Option = txtBxOption.Text;
Item.Options.Add(userOption);
T must be defined within the scope in which you are working. Therefore, what you have posted will work if your class is generic on T:
public class MyClass<T>
{
private List<T> newList;
public List<T> NewList
{
get{return newList;}
set{newList = value;}
}
}
Otherwise, you have to use a defined type.
EDIT: Per #lKashef's request, following is how to have a List property:
private List<int> newList;
public List<int> NewList
{
get{return newList;}
set{newList = value;}
}
This can go within a non-generic class.
Edit 2:
In response to your second question (in your edit), I would not recommend using a list for this type of data handling (if I am understanding you correctly). I would put the user settings in their own class (or struct, if you wish) and have a property of this type on your original class:
public class UserSettings
{
string FirstName { get; set; }
string LastName { get; set; }
// etc.
}
public class MyClass
{
string MyClassProperty1 { get; set; }
// etc.
UserSettings MySettings { get; set; }
}
This way, you have named properties that you can reference instead of an arbitrary index in a list. For example, you can reference MySettings.FirstName as opposed to MySettingsList[0].
Let me know if you have any further questions.
EDIT 3:
For the question in the comments, your property would be like this:
public class MyClass
{
public List<KeyValuePair<string, string>> MySettings { get; set; }
}
EDIT 4: Based on the question's edit 2, following is how I would use this:
public class MyClass
{
// note that this type of property declaration is called an "Automatic Property" and
// it means the same thing as you had written (the private backing variable is used behind the scenes, but you don't see it)
public List<KeyValuePair<string, string> MySettings { get; set; }
}
public class MyConsumingClass
{
public void MyMethod
{
MyClass myClass = new MyClass();
myClass.MySettings = new List<KeyValuePair<string, string>>();
myClass.MySettings.Add(new KeyValuePair<string, string>("SomeKeyValue", "SomeValue"));
// etc.
}
}
You mentioned that "the property still won't appear in the object's instance," and I am not sure what you mean. Does this property not appear in IntelliSense? Are you sure that you have created an instance of MyClass (like myClass.MySettings above), or are you trying to access it like a static property (like MyClass.MySettings)?
Simple and effective alternative:
public class ClassName
{
public List<dynamic> MyProperty { get; set; }
}
or
public class ClassName
{
public List<object> MyProperty { get; set; }
}
For differences see this post: List<Object> vs List<dynamic>
public class MyClass<T>
{
private List<T> list;
public List<T> MyList { get { return list; } set { list = value; } }
}
Then you can do something like
MyClass<int> instance1 = new MyClass<int>();
List<int> integers = instance1.MyList;
MyClass<Person> instance2 = new MyClass<Person>();
IEnumerable<Person> persons = instance2.MyList;
You could do this but the T generic parameter needs to be declared at the containing class:
public class Foo<T>
{
public List<T> NewList { get; set; }
}
It's possible to have a property of type List<T> but your class needs to be passed the T too.
public class ClassName<T>
{
public List<T> MyProperty { get; set; }
}
Either specify the type of T, or if you want to make it generic, you'll need to make the parent class generic.
public class MyClass<T>
{
etc

Categories