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

私の問題は、このメソッド a を渡しList<Persons>、Person に a のプロパティがあるList<Cars>場合です。これは T ではないため、Convert.ChangeType を使用できません。

では、「リスト」をループして、このオブジェクトのプロパティにアクセスするにはどうすればよいでしょうか。

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

(注意: 未テスト)

編集:まあ、SelectManynon-generic を理解していないので機能しませんIEnumerable。で動作するように変更しましたIEnumerable<object>。少なくとも、それぞれIEnumerable<T>IEnumerable<object>クラス Tの です。

于 2012-08-28T20:10:23.283 に答える