I have structs which can contain other structs and a class with two properties, one for the field name and one for the field value.
Example structs:
public struct MyStruct
{
public string Name;
public ushort Code;
public Details Info;
}
public struct Details
{
public string Architecture;
public string Characteristics;
public uint Size;
}
My class:
public class Item
{
public string Name { get; set; }
public object Value { get; set; }
public Item(string name, object value)
{
Name = name;
Value = value;
}
}
Now I need a function which input parameter is a struct (that could contain other structs) and returns a List of Item. I have a fully working function for structs without other structs in it:
private static List<Item> structToList<T>(T structure)
{
List<Item> items = new List<Item>();
foreach (var field in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
items.Add(new Item(field.Name, field.GetValue(structure)));
return items;
}
I'm pretty sure this can be solved recursively. My first thought was to check if the field is a struct or a value. If it's a struct, call the function again, if it's a value add it to the list. Furthermore i have to declare the instance of my List outside the function, haven't I? Here is the pseudo code I came up with, so I was not able to check if a FieldInfo is a struct and give the function its proper Generic.
List<Item> items = new List<Item>();
private static List<Item> structToList<T>(T structure, List<Item> items)
{
foreach (var field in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
//if(isStructure(field)
// structToList<?>(field, items);
//else
items.Add(new Item(field.Name, field.GetValue(structure)));
}
return items;
}
EDIT:
The distinction of cases works now. For the else clause I went with this answer, where the type is known at execution time, but i get null reference exception. Also field.GetType() doesn't give me the type of the struct.
private List<Item> structToList<T>(T structure, uint offset)
{
foreach (var field in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
if (IsSimple(field.FieldType))
itemList.Add(new Item(field.Name, field.GetValue(structure)));
else
{
// doesn't work
Type t = field.GetType();
MethodInfo method = GetType().GetMethod("structToList")
.MakeGenericMethod(new Type[] { t }); // null reference exception
method.Invoke(this, new object[] { field, 0 });
}
}
return itemList;
}
private static bool IsSimple(Type type)
{
return type.IsPrimitive
|| type.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal));
}
EDIT 2: I came up with two solutions which fit my needs.