marc_s
marc_s

Reputation: 754220

Detecting a collection-type property on a .NET object using reflection

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

Answers (2)

Jason Tower
Jason Tower

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

Daniel Hilgarth
Daniel Hilgarth

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

Related Questions