【问题标题】:Enumerate ICollection<T> property of class using Reflection使用反射枚举类的 ICollection<T> 属性
【发布时间】:2010-09-20 12:07:24
【问题描述】:

我正在尝试在 .NET 4 中为我的 POCO 对象创建一个基类,它将有一个 Include(string path) 方法,其中 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 = ...>”行不起作用,但您希望能明白要点,并且除非 propertyCollection 是可枚举的,否则 foreach 将不起作用。

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

谢谢

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    你不需要反射。为了枚举它,你只需要一个IEnumerableICollection&lt;T&gt; 继承 IEnumerable,所以你所有的集合都是可枚举的。因此,

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

    会起作用的。

    【讨论】:

      【解决方案2】:

      泛型通常在客户端可以在编译时解析泛型类型时使用。 撇开这一点不谈,因为您需要做的就是枚举propertyCollection(将序列的每个元素简单地视为System.Object),您需要做的就是:

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

      这是非常安全的,因为 ICollection&lt;T&gt; 扩展了 IEnumerable&lt;T&gt;,而 IEnumerable 又扩展了 IEnumerableT 实际上最终在运行时是无关紧要的,因为循环只需要 object

      真正的问题是:System.Object 在循环内是否足以满足您的目的?

      【讨论】:

      • 幸运的是,将项目转换为对象就足够了,因为我仍然可以通过 GetMethod 调用 Include 方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多