Reputation: 754220
I am trying to write some code that would iterate over my business objects and dump out their contents into a log file.
For that, I'd like to be able to find all public properties and output their name and value using reflection - and I'd also like to be able to detect collection properties and iterate over those, too.
Assuming two classes like this:
public class Person
{
private List<Address> _addresses = new List<Address>();
public string Firstname { get; set; }
public string Lastname { get; set; }
public List<Address> Addresses
{
get { return _addresses; }
}
}
public class Address
{
public string Street { get; set; }
public string ZipCode { get; set; }
public string City { get; set; }
}
I currently have code something like this which finds all public properties:
public void Process(object businessObject)
{
// fetch info about all public properties
List<PropertyInfo> propInfoList = new List<PropertyInfo>(businessObject.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public));
foreach (PropertyInfo info in propInfoList)
{
// how can I detect here that "Addresses" is a collection of "Address" items
// and then iterate over those values as a "list of subentities" here?
Console.WriteLine("Name '{0}'; Value '{1}'", info.Name, info.GetValue(businessObject, null));
}
}
But I cannot figure out how to detect that a given property (e.g. the Addresses
on the Person
class) is a collection of Address
objects? Can't seem to find a propInfo.PropertyType.IsCollectionType
property (or something similar that would give me the info I'm looking for)
I've (unsuccessfully) tried things like:
info.PropertyType.IsSubclassOf(typeof(IEnumerable))
info.PropertyType.IsSubclassOf(typeof(System.Collections.Generic.List<>))
info.PropertyType.IsAssignableFrom(typeof(IEnumerable))
Upvotes: 2
Views: 3802
Reputation: 21
If you want to avoid the hassle with strings and other things:
var isCollection = info.PropertyType.IsClass &&
info.PropertyType.GetInterfaces().Contains(typeof(IEnumerable));
Upvotes: 1
Reputation: 174279
Just check for IEnumerable
which is implemented by every single collection, even by arrays:
var isCollection = info.PropertyType.GetInterfaces()
.Any(x => x == typeof(IEnumerable));
Please note that you might want to add some special case handling for classes that implement this interface but that should still not be treated like a collection. string
would be such a case.
Upvotes: 4