I am fairly new to Reflection, but have been able to retrieve all fields of my passed class. Now I am trying to retrieve the values of each field, but I'm having an issue with List<T>
.
I have a simple class for testing:
public class MyTestClass
{
public string Name;
public int Age;
public bool Alive;
public List<int> Counters;
public List<string> People;
public List<Tool> Tools;
public string[] Stuff;
public Tool[] NeededTools;
public MyTestClass(string name, int age, bool alive = true)
{
Name = name;
Age = age;
Alive = alive;
Counters = new List<int>();
Counters.Add(7);
People = new List<string>();
People.Add("Seven");
Tools = new List<Tool>();
Stuff = new string[2];
NeededTools = new Tool[3];
}
}
Here is the code I am using:
private void AttachControl(object source, FieldInfo fi, Control control)
{
switch (fi.FieldType.Name)
{
case "Boolean":
(control.Controls[fi.Name] as ComboBox).SelectedIndex = (fi.GetValue(source).ToString().ToUpper() == "TRUE") ? 1 : 0;
break;
case "List`1":
Control listControl = control.Controls[fi.Name];
var listType = fi.FieldType.GetGenericArguments();
var listFields = listType[0].GetFields(
BindingFlags.Public |
BindingFlags.Instance
);
if (listFields.Length > 0)
{
AttachToControls(listFields, listControl.Controls.Cast<Control>().ToArray());
}
else
{
// *** Here is the issue ***
var values = fi.GetValue(source);
listControl.Controls[fi.Name].Text = values[0].ToString();
}
break;
default:
control.Controls[fi.Name].Text = fi.GetValue(source).ToString();
break;
}
}
When I get to Counters
I can retrieve the value var values = fi.GetValue(source);
and during debug I can see the List with the value 7 in it, but it states
cannot apply indexing with [] to an expression of type
object
on the line:listControl.Controls[fi.Name].Text = values[0].ToString();
I assume I need to cast it, but it will not always be an int type. Do I need to write a section for every type or is there an easier way to accomplish what I need?
FYI - I am writing a Class Library that will allow me to pass any class in and auto create a form to edit all fields.
I'd suggest something along the lines of:
var bob = values as IEnumerable;
listControl.Controls[fi.Name].Text = bob?.Cast<object>()?.FirstOrDefault()?.ToString();
Since the thing you want is a string
(not a specific type) then the above code will work fine (assuming values is some form of an enumerable, like a list or an array).
Note, in particular, that IEnumerable
interface is this one, not the more commonly used IEnumerable<T>
. This allows you to use it without a specific type.