I'm sorry in advance for the mess you're about to read, because I'm not 100% sure what I'm searching for.
I have created an entire UI system that automatically grabs a list of properties from various scripts/components on GameObjects (Unity) and creates a fitting UI input variant for them (for example, float gets a single line, Vector3 gets 3 lines, color gets something else etc.).
What goes into UI input fields creation is a Component (that we want to look into), while individual created UI inputs store this Component and Property Name. So when input changes in one of input fields, it does SetValue on Property of a Component. Now I have also created a variant where we peak into a Class of a property and basically list Property's Properties, so the UI input stores Component, Property Name, and subProperty's Name and modifies properties as such. All this works well.
So, now I hit a brick wall with Lists. I would like to treat individual elements of a list as properties so that I could pass them into my preexisting UI scheme.
tl;dr Does List<> treat it's individual elements as Properties, Fields or does it depend on the situation? How do I get these properties, fields or their respective names from this list in order to use them with my mess of an UI system? 0 work for me means treating individual elements of List as properties.
----------------------------
EDIT----------------------------
Again I am sorry for this mess of a question. It is a mixture of confused theory and description of an existing situation that I am trying to shoehorn into my already existing project (which is a bit too over the place to be easily reduced to an example).
If anyone grasped what I was asking for, the single easiest solution was to create a property which prior to listing was equated to an element of a list.
Example looks something like this:
public List<MyCustomClass> myCustomList;
[Listable("ForEdit")]
public myCustomClass myCustomPropertyForEdit
{
get;
set;
}
And before withdrawing properties of myCustomPropertyForEdit's class (myCustomClass) I would simply do:
myCustomPropertyForEdit = myCustomList[0]; //or whatever index is in question
Then later on I would do reflection on "myCustomPropertyForEdit" instead of myCustomList. I highly doubt this will ever help anyone because it touches more onto how I built methods for listing properties into my UI, but there it is just in case.
List stores references to objects, by providing an index you get a standard object reference, which you can proceed to query using reflection (do not do it against the list itself as you will get methods of the List class, and notthing related to what the list contains)
take for example:
public Class Tree
{
public int branches;
public Tree(int branch)
{
branches=branch;
}
}
List<Tree> trees = new List<Tree>();
trees.Add(new Tree(3));
now my list has one element at index 0;
so i can do trees[0].branches;
to access the fields/props of an element in trees.
list is not an array, it holds the actual item, allowing you to reference, not just the object but also its own unique variables. as long as they are public in the class.
Related
I'm trying to figure out what types or operations are being used in my code (the code was originally taken from my supervisor, and modified to fit my scenario. It works, but I just need to clear a few things up and I know StackOverflow is a jackpot for clearing up any doubts :) ). The idea is to use C# to read an XML file with information on name/dimensions of four walls, compile all the info in a class (or a list... or both? I have some confusion here) and Instantiate these walls in Unity3d during runtime. The Unity parts I'm good with, but I need some help understanding what my C# stuff does.
One file, Wall.cs:
public class Wall
{
public string Name { set; get; }
public float Width { set; get; }
public float Length { set; get; }
}
Similarly, the XML file has parent tag "Walls", child tag "Wall" and subchild tags of "Name", "Width", "Length".
Main file ReadWalls.cs:
public class ReadWalls : MonoBehaviour {
public static List<Wall> ListofWalls = new List<Wall>();
public static List<Wall> ReadWallsXML(){
In this function there's a bunch of stuff to load the XML, using stuff like XmlNodeList, etc. I don't really care too much about this stuff but if anyone has any further info I wouldn't mind!
Then is a foreach loop that iterates through the XML such that it analyzes one Wall at a time. Inside it:
{Wall w = new Wall();
The next nested foreach analyzes one category (name or dimensions) at a time, at the subchild tag level in relation to the XML:
foreach (//code specifying subchild tag level)
{if (XmlNodeid.Name == "Name") {w.Name = XmlNodeid.InnerText;
//Similar if statements for "Width" and "Length", with w.Width and w.Length respectively.} //end of inner foreach
ListofWalls.Add(w);} //end of outer foreach
return ListofWalls;} //end of function
void Start()
{WallsList = ReadWallsXML();
Here in the start function, I want to print all of the information into the console (name, length, width) using Debug.Log. The following works (just printing the name for simplicity):
foreach (Wall thiswall in WallsList)
{Debug.Log(thiswall.Name);}
If I try it this way, I get an error
foreach (Wall.Name thiswallsname in WallsList)
{Debug.Log(thiswallsname);}
}//end of class
Intellisense tells me "The type 'Name' does not exist in the type 'Wall''. So, what is Wall? My understanding was that we initiated it as a Class, with Properties of Name, Length, Width. To access properties, we use the dot operation (?). So why wouldn't Wall.Name access the Name property for each Wall object that was created? Also, why is the error saying Wall is a type? And one more thing, is Wall a list, class, or both? Intellisense says it's a Class (Line 2 of ReadWalls.cs) which makes sense. But where does the list aspect come into play? How are its properties related to the list?
Note that I took a significant amount of code out for (some) brevity, and also changed a few properties/names because my real code is quite lengthy. If you notice any logical or syntax errors, worry not, because the code works. The last part of this question is the most important: I just need help in analysing what the types of my variables/data are. I apologise if I've made any other mistakes, total noob here (to StackOverflow, C#, Unity and object oriented programming) if you couldn't tell already. Also thanks in advance!
Name is a property of the Wall class, not a type of its own. The type of Name is string. Also, when you attempt foreach(Wall.Name thiswallsname in WallsList) you are, if it were a correct type, asking for each item in a list of that type. By that I mean that you are telling the code that you are expecting WallsList to be a collection of the type Wall.Name when it is actually a collection of Wall instances.
If you wanted to access the Name property of each Wall in the collection you would need to do the following:
foreach(Wall wall in WallsList)
{
Debug.WriteLine(string.Format("Name: {0}", wall.Name));
}
Which you show that you already have something basically identical to that.
Wall is a class, WallsList is a List<Wall> type. Basically a collection typed so that each item in the collection is strongly typed as a Wall. It is the same as the variable you have defined above ListOfWalls. As a note on List<T>: Any class can be made into a list of itself by defining a variable as a type of List<ClassName> - for instance List<string> will give you a list of string variables, List<int> will be a list of integers, List<List<int>> will be a list of integer lists... so on and so forth.
To print the values of each of the properties you would need to list each one out within the foreach loop:
foreach(Wall wall in WallsList)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(string.Format("Name: {0}", wall.Name));
sb.AppendLine(string.Format("Width: {0}", wall.Width.ToString()));
sb.AppendLine(string.Format("Length: {0}", wall.Length.ToString()));
Debug.WriteLine(sb.ToString());
}
Of course, you could also look into reflection to dynamically retrieve a list of property names and values from the Wall class within the foreach loop, but using the above example will work just as well if you already know the property names.
Also, why is the error saying Wall is a type? And one more thing, is
Wall a list, class, or both?
Wall is a class—the words "type" and "class" here are interchangeable. WallsList, as the name would imply, is a list made up of Wall objects.
So why wouldn't Wall.Name access the Name property for each Wall
object that was created?
The foreach statement allows you a shorthand way to iterate through collections (specifically, anything that implements the IEnumerable interface). Most commonly, you'll use this with List or Array objects. But both Lists and Arrays are made up of a certain type of objects that is declared when they are created. In this example, your WallsList object is defined as List<Wall>: it's a collection of Wall objects. So when the foreach is iterating through, it only pulls out each Wall object as a whole, not the individual properties.
To access properties, we use the dot operation (?). So why wouldn't
Wall.Name access the Name property for each Wall object that was
created?
In as simple terms as I can think of, you have to create an instance of a class before you can access the properties. Declaring Wall blah = new Wall(); allocates a space in memory for that new object and then blah.Name = "hello"; sets the property. Trying to call Wall.Name = "hello"; directly results in an error because you're trying to set something that, from the computer's perspective, doesn't exist.
I'm writing a C# application that does some things with baseball statistics. I'm getting the data from an XML web service. I want to completely separate the presentation-business-data layers. In that vain I have created a service class to interact with the web service and to create objects from the data, a set of business classes (i.e. player, team, league), and the objects needed for my presentation layer.
I don't want to load the statistics into the player class because there are more than 200 statistics, and I'm not going to need them every time I instantiate the player class. For each statistic I need its abbreviation, description, XML attribute name, and value.
Question: What C# data-structures or method could be used to present more than two properties and allow several of them to be static across all instances of the datatype and allow at least one to be writable at run-time?
I started to create a "statistic" class like this:
public class BaseballStatistic
{
public string Abbreviation;
public string Description;
public string XmlAttributeName;
public string Value;
public BaseballStatistic(string abbreviation, string description, string xmlAttributeName)
{
Abbreviation = abbreviation;
Description = description;
XmlAttributeName = xmlAttributeName;
}
}
The problem with this is that I'll never need to change the abbreviation, description, or XML attribute name at run-time.
If I only needed the abbreviation and value, I'd use a Dictionary or some other Key/Value pair.
I started to create a statistic class with abbreviation, description, XML attribute name, and value members. But the only one of those that will ever change at runtime is the value - so this didn't feel like the right answer. (Imagine 500 players, each with an array of statistic objects, and those object are the exact same for all players except for the value.)
I considered creating a multidimensional array, but with so many constant values, it seems wasteful to load such a thing at run time.
I feel like I should know this.
I should add this: because there are so many different statistics that I can use, it would be great if I could find a solution that would expose them to Intellisense. For example:
Statistic g = Stats.GamesPlayed
It sounds like you need one class for "a statistic" - and then a Dictionary<PlayerStat, int> (or whatever the value would be).
The PlayerStat class would know about the abbreviation, description and XML attribute name - and I'd suggest that you probably create a Dictionary<string, PlayerStat> statically to map from abbreviation to statistic, and another one to map from XML attribute to abbreviation.
You may not even need the Dictionary<PlayerStat, int> in your Player class... you could always add an indexer or method which looked things up lazily. (Be careful with this, however - you may find that loading many things lazily will be more expensive than loading everything in one go. You may want to break the statistics into categories, and load all the stats for a single category when you load one of them. Basically, if there are clumps of stats that are usually used together...)
I would like to create sample program.
It will has Department Class,Position Class,Employee Class.
Each department will has any positions. I don't know that how I should specify that.
And I don't use DataBase. It is only to learn OOP in Console.
Whether to use an Enum or a Collection mainly depends on the following criteria:
How often you expect the available values of positions to change?
Who will conduct the changes?
Does the Position only have an Id and a Text or do you expect it to have other data fields as well.
Will each position be available once per Department and not several times?
If your answers are
Seldom.
The developer.
Only Id and Text.
Yes
then an Enum with a FlagsAttribute is a good option. However, if there is any doubt about this, creating a class for a Position and adding a collection is a better way as it is more flexible. It also allows you to add the same kind of position several times to a Department, if this is a requirement.
Though you don't use a database up to now, also note that adding an Enum property to the Department is much easier to save in comparison to have related positions that should go into a separate structure.
Based upon your comment, I suggest to add a constructor to set the relevant data in a department upon creation (you might also think about whether the data should be private fields as you could not access them from the outside):
class Department
{
public Department(Dep departmentType, IEnumerable<Position> positions, int employeeCount)
{
this.departmentType = departmentType;
this.positions = new List<Position>(positions);
this.employeeCount = employeeCount;
}
Dep departmentType;
List<Position> positions;
int employeecount;
}
You could then create a new Department like this:
var dep = new Department(Dep.Electric,
new Position() [] { new Position(), new Position() },
5);
Please note that you might also need to add a constructor to your Position class. In the above sample, I create two Position objects that are added to the Positions list in the Department.
If position is going to be just string values, its best to have them as enum and write your logic around it.
If new position gets added to the enum, the logic will break and it would help you to write specific functionality for each position.
You can write a class around this position enum to alter its functionality based on the enum.
Suppose I have a table in my database that is made up of the following columns, 3 of which uniquely identify the row:
CREATE TABLE [dbo].[Lines]
(
[Attr1] [nvarchar](10) NOT NULL,
[Attr2] [nvarchar](10) NOT NULL,
[Attr3] [nvarchar](10) NOT NULL,
PRIMARY KEY (Attr1, Attr2, Attr3)
)
Now, I have an object in my application that represents one of those lines. It has three properties on it that correspond to the three Attr columns in the database.
public class Line
{
public Line(string attr1, string attr2, string attr3)
{
this.Attr1 = attr1;
this.Attr2 = attr2;
this.Attr3 = attr3;
}
public Attr1 {get; private set;}
public Attr2 {get; private set;}
public Attr3 {get; private set;}
}
There's a second object in the application that stores a collection of these line objects.
Here's the question: What is the most appropriate design when referencing an individual line in this collection (from a caller's perspective)? Should the caller be responsible for tracking the index of the line he's changing and then just use that index to modify a line directly in the collection? Or...should there be method(s) on the object that says something to the effect of:
public GetLine(string attr1, string attr2, string attr3)
{
// return the line from the collection
}
public UpdateLine(Line line)
{
// update the line in the collection
}
We're having a debate on our team, because some of us think that it makes more sense to reference a line using their internal index in the collection , and others think there's no reason to have to introduce another internal key when we can already uniquely identify a line based on the three attributes.
Thoughts?
Your object model should be designed so that it makes sense to an object consumer. It should not be tied to the data model to the greatest extent practical.
It sounds like it is more intuitive for the object consumer to think in terms of the three attributes. If there are no performance concerns that speak to the contrary, I would let the object consumer work with those attributes and not concern him with the internal workings of data storage (i.e. not require them to know or care about an internal index).
I think the base question you are encountering is how much control the user of your API should have over your data, and what exactly you expose. This varies wildly depending on what you want to do, and either can be appropriate.
The question is, who is responsible for the information you wish to update. From what you have posted, it appears that the Line object is responsible the information, and thus I would advocate a syntax such as Collection.GetLine(attr1, attr2, attr3).UpdateX(newX) and so forth.
However, it may be that the collection actually has a greater responsibility to that information, in which case Collection.UpdateX(line, newX) would make more sense (alternatively, replace the 'line' arg with 'attr1, attr2, attr2').
Thirdly, it is possible, though unlikely (and rarely the best design IMHO) that the API user is most responsible for the information, in which case an approach you mentioned where the user handles tracking Line indices and directly modifies information.
You do not want the calling object to "track the index of the line he's changing" - ever. This makes your design way too interdependent, pushes object-level implementation decisions off onto the users of the object, makes testing more difficult, and can result in difficult to diagnose bugs when you accidentally update one object (due to key duplications) when you meant to update another.
Go back to OO discipline: the Line object that you are returning from the GetLine method should be acting like a real, first class "thing."
The complication, of course, comes if you change one of the fields in the line object that is used as part of your index. If you change one of these fields, you won't be able to find the original in the database when you go to do your update. Well, that is what data hiding in objects is all about, no?
Here is my suggestion, have three untouchable fields in the object that correspond to its state in the database ("originalAttr1", "originalAttr2", "originalAttr3"). Also, have three properties ("attr1", "attr2", "attr3") that start out with the same values as the originals but that are Settable. Your Getters and Setters will work on the attr properties only. When you "Update" (or perform other actions that go back to the underlying source), use the originalAttrX values as your keys (along with uniqueness checks, etc.).
This might seem like a bit of work but it is nothing compared to the mess that you'll get into if you push all of these implementation decisions off on the consumer of the object! Then you'll have all of the various consumers trying to (redundantly) apply the correct logic in a consistent manner - along with many more paths to test.
One more thing: this kind of stuff is done all the time in data access libraries and so is a quite common coding pattern.
What is the most appropriate design
when referencing an individual line in
this collection (from a caller's
perspective)?
If the caller is 'thinking' in terms of the three attributes, I would consider adding an indexer to your collection class that's keyed on the three attributes, something like:
public Line this[string attr1, string attr2, string attr3] {
get {
// code to find the appropriate line...
}
}
Indexers are the go-to spot for "How Do I Fetch Data From This Collection" and, IMO, are the most intuitive accessor to any collection.
I always prefer to just use a single column ID column even if there is a composite key that can be used. I would just add an identity column to the table and use that for look up instead. Also, it would be faster because query for a single int column would perform better than a key spanned across three text columns.
Having a user maintain some sort of line index to look up a line doesn't seem very good to me. So if I had to pick between the two options you posed though, I would use the composite key.
If the client is retrieving the Line object using three string values, then that's what you pass to the getter method. From that point on, everything necessary to update the object in the database (such as a unique row ID) should be hidden within the Line object itself.
That way all the gory details are hidden from the client, which protects the client from damaging it, and also protects the client from any future changes you might make to the dB access within the Line object.
I would like to generate a list of differences between 2 instances of the the same object. Object in question:
public class Step
{
[DataMember]
public StepInstanceInfo InstanceInfo { get; set; }
[DataMember]
public Collection<string> AdHocRules { get; set; }
[DataMember]
public Collection<StepDoc> StepDocs
{...}
[DataMember]
public Collection<StepUsers> StepUsers
{...}
}
What I would like to do is find an intelligent way to return an object that lists the differences between the two instances (for example, let me know that 2 specific StepDocs were added, 1 specific StepUser was removed, and one rule was changed from "Go" to "Stop"). I have been looking into using a MD5 hash, but I can't find any good examples of traversing an object like this and returning a manifest of the specific differences (not just indicating that they are different).
Additional Background: the reason that I need to do this is the API that I am supporting allows clients to SaveStep(Step step)...this works great for persisting the Step object to the db using entities and repositories. I need to raise specific events (like this user was added, etc) from this SaveStep method, though, in order to alert another system (workflow engine) that a specific element in the step has changed.
Thank you.
You'll need a separate object, like StepDiff with collections for removed and added items. The easiest way to do something like this is to copy the collections from each of the old and new objects, so that StepDiff has collectionOldStepDocs and collectionNewStepDocs.
Grab the shorter collection and iterate through it and see if each StepDoc exists in the other collection. If so, delete the StepDoc reference from both collections. Then when you're finished iterating, collectionOldStepDocs contains stepDocs that were deleted and collectionNewStepDocs contains the stepDocs that were added.
From there you should be able to build your manifest in whatever way necessary.
Implementing the IComparable interface in your object may provide you with the functionality you need. This will provide you a custom way to determine differences between objects without resorting to checksums which really won't help you track what the differences are in usable terms. Otherwise, there's no way to determine equality between two user objects in .NET that I know of. There are some decent examples of the usage of this interface in the help file for Visual Studio, or here. You might be able to glean some directives from the examples on clean ways to compare the properties and store the values in some usable manner for tracking purposes (perhaps a collection, or dictionary object?).
Hope this helps,
Greg