- Home /
How to retrieve properties from a class without prior knowledge of what those properties are?
I'm sure I'm missing a trick here. I think I may have even done this before, but right now I'm stumped and have been for the last few hours.
Here's the code snippet I wish to change:
void populateList (List<Item> itemList) {
for(int i = 0; i < itemList.Count; i++){
GameObject item = Instantiate(listEntry);
UnityEngine.UI.Text output = item.AddComponent<Text>();
output.text = (itemList[i].name + " Minimum damage: " + itemList[i].minDamage);
output.font = listFont;
item.transform.SetParent(transform);
}
}
It's the "output.text... etc." line that I'm concerned with. I'm trying to stick to the single responsibility principle and it irks me that I'm referring to an item's properties explicitly in a script which shouldn't be concerned with such things. Also, although the itemList currently only contains weapons it will soon contain other items which will need to display a variety of information dependent on their type (defense values for armour, etc).
I was thinking along the lines of changing this method to display any information which is passed to it, and then choosing the information to be passed in my Item class and its children. How would I achieve this, or what other solutions would you recommend?
I feel like I'm overthinking it and have overlooked an obvious solution at this point.
Apologies if there are no paragraphs in this. I'm not quite sure how to insert them.
I am making several assumptions but it sounds like you want to offload the responsibility of stringing together these properties in order to display a sort of "item blurb" if you will. in my line of thinking I reckon an item should know its own properties, it would be peculiar if it did not. You might want to consider pushing this functionality onto Item as abstract (no implementation) assu$$anonymous$$g weapon or whatever implements Item and item is itself abstract, then you can define what this property or function then returns, then in your populateList function you can simply call itemList[i].GetBlurbDescription(). if this is not suitable you could offload the responsibility to a service that builds up the blurb you want to display and just call into that.
Answer by ImpOfThePerverse · May 18, 2018 at 03:26 PM
In most C++ classes, you write a ToString function for your class that lets you output objects of the class via cout. What you'll probably want to do here is create an interface with a GetStatString() function. In each class that you want to print out, implement the interface. The implementation of GetStatString() will be different for each class. I can't really think of a way to automate writing the GetStatString() function, since you won't necessarily be wanting to print every variable in the class, and you need some way to associate a string name with the variable that won't necessarily be the same as the variable name.
Looking over your code, it looks like your items are all inheriting from an Item class, so you could add the GetStatString() function there and implement it in the derived classes instead of using an interface. Line 5 would end up looking like:
output.text = item.GetStatString();
This does indeed answer my question, but it also makes me rethink my approach. A single string is probably not ideal in the long term, as I'll likely have multiple fields to fill on my UI. I believe I know how I will achieve this.
$$anonymous$$y question was flawed, but both of the answers I received have aided my comprehension and I thank you.
Answer by Happeloy · May 18, 2018 at 04:09 PM
I'm not totally sure if this is what you are looking for, but you can iterate through all fields in a class like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestScript : MonoBehaviour {
void Start () {
System.Type type = typeof(ExampleClass);
System.Reflection.FieldInfo[] fieldInfo = type.GetFields();
foreach(System.Reflection.FieldInfo f in fieldInfo){
Debug.Log("Field: " + f.Name);
}
}
}
public class ExampleClass
{
public string testString;
public int testInt;
public Vector3 testVector;
}
Ah. I wanted the values themselves, not the names of the properties. The example you gave is something I didn't know was possible though, and I'm happy to have learned about it.
Your answer
Follow this Question
Related Questions
How do I create public read-only properties? 3 Answers
iPhoneKeyboard Set Text after validation 1 Answer
How do I expose public properties in the same way the inspector does via a gui in game? 1 Answer
Setting a property, and then making it readonly. (c#) 2 Answers
What is the correct way to set FBX user properties for import in Unity ? 1 Answer