Fill variable if MemberInfo name is same as a string

I’m trying to build a fast system to fill variables on classes from a text file. I surely can do this in a simple way by reading certain lines on a text file, but I’m trying to do this dynamic as possible without the need to hardcode almost everything.

I use a static class to fill a Dictionary with key val strings that are taken from the text file (splitting each line), and I can get to the point to see if the text file have the variable names equal to the class variables names using MemberInfo, the problem is I don’t know how to return back that variable as depending on the type I have to parse the string to int or float or anything else. This is what I’ve done so far on retrieving the text file strings:

static public void GetVariableLine (string path, MemberInfo m) {
	
	string text = projectPath + "/" + path;
	
using (StreamReader sr = new StreamReader(text)) {

	string line;

    while ((line = sr.ReadLine()) != null) {
		string[] newLine = line.Split('=');
	    keyVal.Add(newLine[0], newLine[1]);
			
	    foreach (MemberInfo member in m.GetType().GetMembers()) {
		    if(member.Name == newLine[0])
					Debug.Log (member.Name);
		}
			
		Debug.Log (newLine[1]);
    }
		
	sr.Close();
	keyVal.Clear();
		
	}
}

And I call this function by the script I want the variables filled:

void Start () {
	NFParser.GetVariableLine(file, this.GetType());
}

So as you can see for now there are only debug logs in there, what I would like to do is to get back the variable from the dictionary for the corrisponding memberinfo name of the class, but I’m at a dead end, not even sure this is possible.

Firstly - I believe there is an error in your method signature. You have

MemberInfo m

and later you’re calling

m.GetType().GetMembers()

so I guess the parameter should be actual object instance.

Anyway, if I had to implement filling an object using values from file, I would do it this way:

static Dictionary<string, string> keyVal = new Dictionary<string, string>();

static public void FillObjectDataFromFile(string path, object instance)
{
    string text = projectPath + "/" + path;

    var dicPropertyInfosByName = instance.GetType().GetProperties().ToDictionary(x => x.Name);
    var dicFieldInfosByName = instance.GetType().GetFields().ToDictionary(x => x.Name);

    keyVal.Clear();
    using (StreamReader sr = new StreamReader(text))
    {
        string line;

        while ((line = sr.ReadLine()) != null)
        {
            string[] newLine = line.Split('=');
            keyVal.Add(newLine[0], newLine[1]);
        }
    }

    foreach (var kv in keyVal)
    {
        if (dicFieldInfosByName.ContainsKey(kv.Key))
        {
            SetFieldValue(instance, dicFieldInfosByName[kv.Key], kv.Value);
        }
        else if (dicPropertyInfosByName.ContainsKey(kv.Key))
        {
            SetPropertyValue(instance, dicPropertyInfosByName[kv.Key], kv.Value);
        }
    }
}

private static void SetFieldValue(object instance, FieldInfo fieldInfo, string value)
{
    fieldInfo.SetValue(instance, GetConvertedValue(value, fieldInfo.FieldType));
}

private static void SetPropertyValue(object instance, PropertyInfo propertyInfo, string value)
{
    propertyInfo.SetValue(instance, GetConvertedValue(value, propertyInfo.PropertyType), null);
}

private static object GetConvertedValue(string value, Type type)
{
    if (type == typeof(string) || type == typeof(object))
    {
        return value;
    }
    if (type == typeof(int))
    {
        return int.Parse(value);
    }
    if (type == typeof(float))
    {
        return float.Parse(value, NumberFormatInfo.InvariantInfo);
    }
    // if conditions for other types

    throw new Exception("Unknown type: " + type.FullName);
}

This is of course some basic code, because it works for public properties/fields only, and is able to convert a few types only, but I think you should be able to expand it to fit your needs.

I hope I didn’t misunderstand you, but if this is not the answer you expected, please comment :slight_smile: