I know how to loop through all properties of a class, but what if on property are List, how can I loop through all properties of T class? See comments in my code. I have read 20 of the suggested similar questions but I don't get any answer. Either I am stupid and this is a duplicate (sorry for that in that case) or the answer is needed.
public class HeaderClass
{
public int HeaderId { get; set; }
public string HeaderText { get; set; }
public string HeaderText2 { get; set; }
public RowClass Rows { get; set; }
}
public class RowClass
{
public int HeaderId { get; set; }
public int SubRowId { get; set; }
public string SubText { get; set; }
public string SubText2 { get; set; }
}
//Call this to get all properties of HeaderClass
Getdata(Headers);
void Getdata(object myObject)
{
foreach (PropertyInfo pi in myObject.GetType().GetProperties())
{
string currentPropertyName = pi.Name;
string currentPropertyType;
//First of all, are there a better way to direct get the TypeName?
if(pi.PropertyType == typeof(string))
{
currentPropertyType = "string";
}
else if(pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(bool?))
{
currentPropertyType = "bool";
}
else if(pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?))
{
currentPropertyType = "DateTime";
}
//If the Type is List<T>
if(pi.PropertyType.Name.ToLower() == "list`1")
{
Type itemType = pi.PropertyType.GetGenericArguments()[0];
//How to convert this to an object so I can loop through all properties of class SubRows
}
}
}
You can get all properties of list type like this
if(pi.PropertyType.IsGenericType && !pi.PropertyType.Name.Equals("Nullable`1"))
// or if(pi.PropertyType.Name.ToLower() == "list`1")
{
foreach (var property in pi.PropertyType.GenericTypeArguments[0]
.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
// BindingFlags.DeclaredOnly => Inherited members are not considered
{
}
}
First of all you should not check the name, use pt.GetGenericTypeDefinition() == typeof(List<>)
, second try this:
class Foo
{
public List<Bar> Bars {get;set;}
}
class Bar
{
public int I1 { get; set; }
public string S1 { get; set; }
}
var x = new Foo
{
Bars = new List<Bar> { new Bar { S1 = "asdd"}}
};
foreach (var prop in typeof(Foo).GetProperties())
{
var pt = prop.PropertyType;
if (pt.IsGenericType && pt.GetGenericTypeDefinition() == typeof(List<>))
{
var en = (prop.GetValue(x) as IEnumerable).Cast<object>();
var innerType = pt.GetGenericArguments()[0];
foreach (var innerProp in innerType.GetProperties())
{
Console.WriteLine(innerProp.Name); // prints I1 S1
Console.WriteLine(innerProp.GetValue(en.First())); // prints "asdd"
}
}
}
How to convert this to an object so I can loop thrue all properties of class SubRows
So you don't need to convert it to object, pi.PropertyType.GetGenericArguments()[0]
returns you an instance of Type
which has .GetProperties()
method on it.
static void GetData(object myObject)
{
foreach (PropertyInfo pi in myObject.GetType().GetProperties())
{
string currentPropertyType;
Console.WriteLine(pi.Name);
//First of all, are there a better way to direct get the TypeName?
if (pi.PropertyType == typeof(string))
{
currentPropertyType = "string";
}
else if (pi.PropertyType == typeof(bool) || pi.PropertyType == typeof(bool?))
{
currentPropertyType = "bool";
}
else if (pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?))
{
currentPropertyType = "DateTime";
}
// **view the next section...**
}
}
To get the generic type definition of the property type and compare it with List<>
// If the Type is List<T>
// To check if the type of the property is List<>, we have to first get its
// generic type definition then we can compare it with List<>.
// If we get null (maybe because we have not a generic type) we avoid the
// comparison with List<> and the condition is false. If we get it,
// we compare and if the types match, we can call GetData on the list's items.
if (GetGenericTypeDefinition(pi.PropertyType)?.Equals(typeof(List<>)) ?? false)
{
Type itemType = pi.PropertyType.GetGenericArguments()[0];
var myListObject = (IEnumerable<object>)pi.GetValue(myObject);
foreach (var item in myListObject)
{
GetData(item);
}
}
This is the implementation of the method GetGenericTypeDefinition
static Type GetGenericTypeDefinition(Type type)
{
// If type is not a generic type we can't get its generic definition so we return null
if (!type.IsGenericType)
return null;
return type.GetGenericTypeDefinition();
}
I've included a little Main method to test my implementation easily.
class Class1
{
public int Val { get; set; }
public List<Class2> Items { get; set; }
}
class Class2
{
public int Val1 { get; set; }
public int Val2 { get; set; }
}
static void Main(string[] args)
{
Class1 obj = new Class1
{
Val = 2,
Items = new List<Class2>
{
new Class2
{
Val1 = 15,
Val2 = 22
},
new Class2
{
Val1 = 107,
Val2 = 87
},
new Class2
{
Val1 = 44,
Val2 = 18
}
}
};
GetData(obj);
Console.ReadKey();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.