使用反射检测.NET对象上的集合类型属性

时间:2013-03-22 13:30:32

标签: .net object reflection collections

我正在尝试编写一些代码来迭代我的业务对象并将其内容转储到日志文件中。

为此,我希望能够找到所有公共属性并使用反射输出其名称和值 - 我还希望能够检测集合属性并迭代那些也是。

假设有两个类:

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; }
}

我目前的代码类似于查找所有公共属性的代码:

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));
    }
}

但是我无法弄清楚如何检测某个属性(例如Addresses类的Person)是 Address个对象的集合?似乎无法找到propInfo.PropertyType.IsCollectionType属性(或类似的东西会给我我正在寻找的信息)

我(尝试失败)尝试过这样的事情:

info.PropertyType.IsSubclassOf(typeof(IEnumerable))
info.PropertyType.IsSubclassOf(typeof(System.Collections.Generic.List<>))

info.PropertyType.IsAssignableFrom(typeof(IEnumerable))

2 个答案:

答案 0 :(得分:2)

只需检查由每个集合实现的IEnumerable,即使是数组:

var isCollection = info.PropertyType.GetInterfaces()
                       .Any(x => x == typeof(IEnumerable));

请注意,您可能希望为实现此接口的类添加一些特殊情况处理,但仍不应将其视为集合。 string就是这种情况。

答案 1 :(得分:0)

如果要避免使用字符串和其他东西的麻烦:

    var isCollection = info.PropertyType.IsClass && 
info.PropertyType.GetInterfaces().Contains(typeof(IEnumerable));