1

我正在尝试制作模型反射工具。到目前为止,我已经走了很长一段路,但现在我被困住了。

我有这个

public static void RenderModelList(List<T> modelList)
{
   foreach (T model in modelList)
   {
      PropertyInfo[] properties = model.GetType().GetProperties();
      foreach (PropertyInfo property in properties)
      {
         object propValue = property.GetValue(model, null);
         //Check if the property is a collection and do recursion 
         if (propValue != null)
         {
            if (isCollection(propValue))
            {   
               //This only works for Lists of the same <T> 
               List<T> li = Convert.ChangeType(propValue, propValue.GetType()) as List<T>;
               if (li != null)
               {
                  if (li.Count > 0)
                  {
                     RenderModelList(li, loop);
                  }                                            
               }
               else
               {
                  //Its another type what to do?
                  // Create a List<> of unknown type??         
               }
            }
         }
      }
   }
}

我的问题是,如果我通过这个方法 aList<Persons>并且 Person 有一个属性是 a List<Cars>- 我不能使用 Convert.ChangeType - 因为这不是 T。

那么如何循环通过“列表”并访问该对象的属性?

4

2 回答 2

4

在我看来,您的方法可以更松散地输入:

public static void RenderModelList(IEnumerable list)
{
    foreach (object model in list)
    {
        ...
    }
}

然后你只需要转换为IEnumerable,而不是特定的序列或列表类型。

于 2012-08-28T20:09:48.443 回答
3

好吧,你的方法不应该依赖T. 您可以IEnumerable改为使用(不是IEnumerable<T>,因为它再次取决于T)。请注意,每个List<T>implements IEnumerable,因此您的方法将与它们一起使用;但是,其他集合也经常实现IEnumerable。这可能是也可能不是您需要的。

如果您选择建议的方式,您的测试isCollection将是这样的:

IEnumerable propValueAsEnumerable = propValue as IEnumerable;
if (propValueAsEnumerable != null)
    RenderModelList(propValueAsEnumerable);

我可能会将您的方法重构为类似的东西:

IEnumerable<object> GetPropertyValuesFlat(object o)
{
    return o.GetType()
            .GetProperties()
            .Select(pi => pi.GetValue(o, null))
            .Where(pv => pv != null)
            .SelectMany(pv => pv is IEnumerable<object> ?
                          (IEnumerable<object>)pv : new[] {pv});
}

//...
foreach (object p in GetPropertyValuesFlat(o))
    render(p);

(注意:未经测试)

编辑:好吧,因为SelectMany不理解 non-generic 所以不能工作IEnumerable。将其更改为与IEnumerable<object>. 至少,每个IEnumerable<T>都是IEnumerable<object>T 类。

于 2012-08-28T20:10:23.283 回答