- Home /
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.
Answer by ArkaneX · Sep 02, 2013 at 01:44 PM
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 :)
You understood perfectly what I'm trying to do, just a question I need a specific namespace for Type, as I'm getting back an error on this and is weird.
Namespaces required for the above code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Globalization;
Never$$anonymous$$d I stupiditly forgot to add System; By the way this work flawlesly, I will have only to add more types. Thank you.