使用Reflection </t>枚举类的ICollection <t>属性

时间:2010-09-20 12:07:24

标签: c# reflection

我正在尝试为.NET 4中的POCO对象创建一个基类,它将具有Include(字符串路径)方法,其中path是“。”要枚举的继承类的嵌套ICollection属性的分隔导航路径。

例如,给定以下类别;

public class Region
{
    public string Name { get; set; }
    public ICollection<Country> Countries { get; set; }
}
public partial class Region : EntityBase<Region> {}

public class Country
{
    public string Name { get; set; }
    public ICollection<City> Cities { get; set; }
}
public partial class Country : EntityBase<Country> {}

public class City
{
    public string Name { get; set; }
}
public partial class City : EntityBase<City> {}

我希望能够做到这样的事情;

Region region = DAL.GetRegion(4);
region.Include("Countries.Cities");

到目前为止,我有以下内容;

public class EntityBase<T> where T : class 
{
    public void Include(string path)
    {
        // various validation has been omitted for brevity
        string[] paths = path.Split('.');
        int pathLength = paths.Length;
        PropertyInfo propertyInfo = type(T).GetProperty(paths[0]);
        object propertyValue = propertyInfo.GetValue(this, null);
        if (propertyValue != null)
        {
            Type interfaceType = propertyInfo.PropertyType;
            Type entityType = interfaceType.GetGenericArguments()[0];

            // I want to do something like....
            var propertyCollection = (ICollection<entityType>)propertyValue;
            foreach(object item in propertyCollection)
           {
               if (pathLength > 1)
               {
                   // call Include method of item for nested path
               }
           }
        }
    }
}

显然,“var list = ...&gt;” line不起作用,但你希望获得要点,除非propertyCollection是可枚举的,否则foreach将无法工作。

所以这是最后一点,即如果直到运行时我不知道T的类型,我该如何枚举类的ICollection属性?

由于

2 个答案:

答案 0 :(得分:1)

你不需要反思。为了枚举它,您只需要一个IEnumerableICollection<T>继承IEnumerable,因此您的所有收藏都将是枚举。因此,

var propertyCollection = (IEnumerable) propertyValue;
foreach (object item in propertyCollection)
    // ...

会奏效。

答案 1 :(得分:0)

当客户端可以在 compile -time解析泛型类型时,通常会使用泛型。 暂且不说,因为您需要做的只是枚举propertyCollection(将序列的每个元素简单地视为System.Object),您需要做的就是:

var propertyCollection = (IEnumerable)propertyValue;
foreach(object item in propertyCollection)
{
    ...
}    

这是非常安全的,因为ICollection<T>扩展了IEnumerable<T>,而IEnumerable又延伸了Tobject实际上最终在运行时的结果是无关紧要的,因为循环只需要System.Object

真正的问题是:{{1}}在循环中是否足以满足您的目的?