-2

I am trying to get an int array from the method GetValue(this, null), but I only get System.Int32[]. Any ideas? I'm expecting to get as output the value of consequences2 (when the function will be called with textNum = 2), which is [3,4,5], but I only get "System.Int32[]". I need to get the value on runtime because the app I'm developing is a testual game with potentially over 500 of these arrays.

using System.IO;
using UnityEngine;
using System;
using System.Reflection;
using System.Linq;

public class DialogueManager : MonoBehaviour
{
    //999 IS RETURN TO MENU
    //1000 IS CLOSE GAME
    public static DialogueManager instance = null;
    Dialogues dial;
    public string text1 { get; set; }
    public string choices1 { get; set; }
    public int[] consequences1 { get; set; }
    public string text2 { get; set; }
    public string choices2 { get; set; }
    public int[] consequences2 { get; set; }
    public string text3 { get; set; }
    public string choices3 { get; set; }
    public int[] consequences3 { get; set; }
    public string text4 { get; set; }
    public string choices4 { get; set; }
    public int[] consequences4 { get; set; }
    public string text5 { get; set; }
    public string choices5 { get; set; }
    public int[] consequences5 { get; set; }
    string fixedName;

    string[] choices;
    string text;
    string[] consequences;
    private void Awake()
    {
        if(instance == null)
        {
            instance = this;
        }
        dial = new Dialogues();
        StreamReader sR = new StreamReader(Application.dataPath + "/GameData/dialogues.json");
        string json = sR.ReadToEnd();
        dial = JsonUtility.FromJson<Dialogues>(json);
        text1 = dial.text1;
        choices1 = dial.choices1;
        consequences1 = dial.consequences1;
        text2 = dial.text2;
        choices2 = dial.choices2;
        consequences2 = dial.consequences2;
        text3 = dial.text3;
        choices3 = dial.choices3;
        consequences3 = dial.consequences3;
        text4 = dial.text4;
        choices4 = dial.choices4;
        consequences4 = dial.consequences4;
        text5 = dial.text5;
        choices5 = dial.choices5;
        consequences5 = dial.consequences5;
    }
    public string GetText(int currentText)
    {
        fixedName = "text" + currentText;
        string output = typeof(DialogueManager).GetProperty(fixedName).GetValue(this, null).ToString();
        Debug.Log(output);
        return output;
    }
    public string GetTextChoices(int textNum)
    {
        fixedName = "choices" + textNum;
        string output = typeof(DialogueManager).GetProperty(fixedName).GetValue(this, null).ToString();
        if (output == "System.String[]")
        {
            output = null;
        }
        return output;
    }
    public int[] GetChoicesConsequences(int textNum)
    {
        fixedName = "consequences" + textNum;
        int[] values = (int[])((dynamic)this).fixedName;
        return values;

    }
}

public class Dialogues
{
    public string text1;
    public string choices1;
    public int[] consequences1;
    public string text2;
    public string choices2;
    public int[] consequences2;
    public string text3;
    public string choices3;
    public int[] consequences3;
    public string text4;
    public string choices4;
    public int[] consequences4;
    public string text5;
    public string choices5;
    public int[] consequences5;
}
MaxGameDev
  • 17
  • 6
  • 3
    https://stackoverflow.com/questions/62503/should-i-use-int-or-int32 – Ive Mar 04 '19 at 10:24
  • 1
    I don't understand the question: `int` is only syntactic sugar for `System.Int32`, so you already do get the int array you expect. – René Vogt Mar 04 '19 at 10:24
  • 4
    Is it necessary to use reflection? There are other ways to shoot youself in the foot) – caxapexac Mar 04 '19 at 10:25
  • debug.log doesnt tend to entirely print out contents of objects, to which an array is just that, if you want it to print out the values, you would do better to be more specific. – BugFinder Mar 04 '19 at 12:39

1 Answers1

0

Instead of

int[] values = (int[]) typeof(DialogueManager).GetProperty(fixedName).GetValue(this, null);

you could try to use

int[] values = (int[]) ((dynamic) this).fixedName;

which should work, because your fixedname property is a public instance property.


Or, better yet, rethink why you need to determine property names at runtime? Would a simple

if(textNum == 1) return this.consequences1; 
else if(textNum == 2) return this.consequences2;
// ...

not do?


EDIT

I just re-read your question. Is your question about the fact that Console.WriteLine prints System.Int32[] when you want it to print the actual array values? If so, you could use

foreach(int v in values) // where values is your int[]
{
    Console.WriteLine(v);
}

which yields

1
2
3

or you could use

Console.WriteLine("[" + String.Join(",", values) + "]");

which yields

[1,2,3]


EDIT 2 Below I wrote code that I think does your task. The main logic happens in the GetPropertyValueSafe method, which is responsible for checking whether the requested property exists, and if it does, get the property value as the specified type.

public class DialogueManager
{
    private static IReadOnlyCollection<PropertyInfo> AllProperties = typeof(DialogueManager).GetProperties();

    private T GetPropertyValueSafe<T>(string propertyName)
    {
        PropertyInfo thePropertyInfo = DialogueManager.AllProperties.SingleOrDefault(x => x.Name == propertyName);

        if (thePropertyInfo is null)
        {
            throw new InvalidOperationException($"Type {this.GetType()} has no property {propertyName}.");
        }

        return (T) thePropertyInfo.GetValue(this);
    }

    private string ArrayToString<T>(T[] array)
    {
        return String.Join(", ", array);
    }

    public string GetText(int currentText)
    {
        return this.GetPropertyValueSafe<string>("text" + currentText);
    }

    public string GetTextChoices(int textNum)
    {
        return this.GetPropertyValueSafe<string>("choices" + textNum);
    }

    public int[] GetChoicesConsequences(int textNum)
    {
        return this.GetPropertyValueSafe<int[]>("consequences" + textNum);
    }

    public string text1 { get; set; } = "Text 1";
    public string choices1 { get; set; } = "Choice 1";
    public int[] consequences1 { get; set; } = new int[] { 1, 2 };
    public string text2 { get; set; } = "Text 2";
    public string choices2 { get; set; } = "Choice 2";
    public int[] consequences2 { get; set; } = new int[] { 1, 2, 3 };

    public static void Main(string[] args)
    {
        DialogueManager d = new DialogueManager();

        Console.WriteLine(d.ArrayToString(d.GetChoicesConsequences(1)));
        Console.WriteLine(d.GetText(1));
        Console.WriteLine(d.GetTextChoices(1));
        Console.WriteLine(d.ArrayToString(d.GetChoicesConsequences(2)));
        Console.WriteLine(d.GetText(2));
        Console.WriteLine(d.GetTextChoices(2));
        Console.ReadLine();
    }
}

Above code yields

> 1, 2
> Text 1
> Choice 1
> 1, 2, 3
> Text 2
> Choice 2
Thomas Flinkow
  • 4,845
  • 5
  • 29
  • 65
  • I need to find the value of the int[] named as fixedname, so the problem is how to get "values" – MaxGameDev Mar 04 '19 at 18:06
  • @MaxGameDev I'm sorry, I still don't know what exactly you want to achieve? Can you please edit your question, and add a **complete** code example, as well as **desired output**? – Thomas Flinkow Mar 04 '19 at 20:03
  • @MaxGameDev please see edit #2. I put what I think is the complete code to your problem. – Thomas Flinkow Mar 05 '19 at 07:38