I have a class called Stats
public class Stats : ScriptableObject
{
public double vitality;
public double stamina;
public double endurance;
}
I also have a class that inherits Stats
public class Equipment : Stats
{
public string name;
// other fields that define equipment
}
I want to be able to get all the fields from the instance of Stats that is inherited from Equipment
So I added this in an Interface class
public void AddStats(Equipment equippedItem)
{
Stats stats = equippedItem as Stats;
if (stats != null)
{
GetPropertyValues(stats);
}
}
public static void GetPropertyValues(System.Object obj)
{
Type t = obj.GetType();
FieldInfo[] fis = t.GetFields(BindingFlags.Instance | BindingFlags.Public);
foreach (var fieldInfo in fis)
Debug.Log(fieldInfo.FieldType " " fieldInfo.Name " " fieldInfo.GetValue(obj));
}
The issue is that it is getting all the fields from the Equipment as well.
How could I make it so that only gets the fields from Stats?
CodePudding user response:
Don't use
Type t = obj.GetType();
but pass in your target type
typeof(Stats);
You could have an overload for this use case and have e.g.
public static void GetPropertyValues(System.Object obj, Type type)
and add a check if the given obj
is of type type
or a subclass
var objType = obj.GetType();
if(objType != type && !objType.IsSubclassOf(type))
{
throw ArgumentException($"Provided object of type {objType.Name} is not derived from {type.Name}");
}
Or the same as a generic
public static void GetPropertyValues<Ttype>(System.Object obj)
and
var objType = obj.GetType();
var type = typeof(T);
if(objType != type && !objType.IsSubclassOf(type))
{
throw ArgumentException($"Provided object of type {objType.Name} is not derived from {type.Name}");
}
Reflection is never going to be "beautiful" ;)
CodePudding user response:
I have found a solution here How to get custom a list of methods with reflection in C# so I created a attribute called stat
[AttributeUsage(AttributeTargets.Field)]
public class Stat : Attribute {}
and I added this attribute to all the variables I wanted to get in my Stats class:
public class Stats : ScriptableObject
{
[Stat] public double vitality;
[Stat] public double stamina;
[Stat] public double endurance;
}
Then I updated my GetPropertyValues method to pick up the attributes and added it to an array.
public static void GetPropertyValues(System.Object obj, double[] array)
{
// Getting the class
Type t = obj.GetType();
// Getting all the fields(Variables)
FieldInfo[] fis = t.GetFields(BindingFlags.ExactBinding | BindingFlags.Instance | BindingFlags.Public);
int arrayLength = 0;
// Itterating through all fields(Variables)
for (int i = 0; i < fis.Length; i )
{
// Filtering through the list and if the field(Variable) is marked with a Stat attribute adds it to array length
arrayLength = i;
}
array = new double[arrayLength];
// Itterating through all the fields(Variables)
for (int i = 0; i < fis.Length; i )
{
// Filtering through the list and if the field(Variable) is marked with a Stat attribute ....
Stat attribute = Attribute.GetCustomAttribute(fis[i], typeof(Stat)) as Stat;
if (attribute != null)
{
Debug.Log(fis[i].Name " " fis[i].GetValue(obj)); // The name of the flagged variable.
array[i] = (Convert.ToDouble(fis[i].GetValue(obj)));
Debug.Log(array[i]);
}
}
}