2013-08-02 60 views
1

是否有一种通用的方法来检索基于字符串值的PropertyInfo,如果深度超过一个级别。C#反射PropertyInfo MVC中的嵌套类

我认为这可能很简单,但我的搜索结果只与我的搜索条件一样好,我想我有一个问题阐明正确的关键字来获得我所追求的搜索结果。

我希望能够做类似下面的(如果键是一个直接财产/一个水平,这完美的作品 - 即键=“的firstName”):

public static PropertyInfo (this HtmlHelper htmlHelper, string key) { 

    PropertyInfo pInfo = htmlHelper.ViewData.Model.GetType().GetProperty(key); 

    return pInfo; 
} 

但有一个办法,我基于字符串返回PropertyInfo单独 时的主要等于更复杂的东西,比如嵌套类,对象,列表等...:

  • 键=“somelist [0] .myproperty “
  • 键=“项[0] .someotherlist [1] .someproperty”(其中物品被定义为List<Item> Items {get; set;}, someotherlist is defined similarly

的方法,可以足够的通用性根据需要(定义的)基本上向下钻取尽可能多的电平?

回答

1

所以这是我想出了......这是即将获得罗嗦,而且大多“思想流”

我有自定义HtmlHelperExtension,并在其中:

PropertyInfo[] pInfoArray = htmlHelper.ViewData.Model.GetType().GetProperties(); 

PropertyInfo pInfo = GetPropertyInfo(pInfoArray, key); 

GetPropertyInfo()方法采用keyPropertyInfo数组,循环访问属性,直到keypart(使用正则表达式从字符串中删除数组的任何指示,因此只留下属性)匹配属性名称。在匹配上,确定这是否是循环中的第一个循环,如果是,则将匹配的属性分配给我的Temp TypePropertyInfo变量。如果keyParts仍然循环遍历,则后续循环现在使用先前设置的临时变量,for循环索引[i]来迭代/向下钻取类结构。每次设置pInfoTemp变量,然后设置pTypeTemp,以便下一个循环可以使用它停止的位置。

private static PropertyInfo GetPropertyInfo(PropertyInfo[] pInfoArray, string key) 
    { 
     PropertyInfo pInfo = null; 
     string[] keyParts = key.Split('.'); 
     Regex arrayRgx = new Regex("\\[\\d*\\]"); 
     PropertyInfo pInfoTemp = null; 
     Type pTypeTemp = null; 

     foreach (PropertyInfo prop in pInfoArray) 
     { 
      string keyPartsTrimmed = arrayRgx.Replace(keyParts[0], ""); // removes '[#]' from string 

      if (keyPartsTrimmed == prop.Name) // match property name 
      { 

       for (int i = 0; i < keyParts.Count(); i++) 
       { 
        if (i == 0) // initial item [0] 
        { 
         pTypeTemp = prop.PropertyType; // gets [0]'s type 
         pInfoTemp = prop;    // assigns [0]'s property info 
        } 
        else 
        { 
         pInfoTemp = GetNestedPropertyInfo(pTypeTemp, arrayRgx.Replace(keyParts[i], "")); // gets [i]'s property info for return or next iteration 
         pTypeTemp = pInfoTemp.PropertyType; // gets [i]'s type for next iteration 
        } 
       } 

       pInfo = pInfoTemp; 
       break; 
      } 
     } 

     return pInfo; 
    } 

接下来的这个方法是由以前的抓取嵌套属性信息,更重要的是用于检测passedItemType是否是列表(没有这个调用,它不能正常工作,因为它无法找到要求的属性在列表<>类型。我需要知道列表项类型是什么。

private static PropertyInfo GetNestedPropertyInfo(Type passedItemType, string passedProperty) 
    { 
     PropertyInfo pInfoOut = null; 

     if (passedItemType.IsGenericType && passedItemType.GetGenericTypeDefinition() == typeof(List<>)) 
     { 
      Type itemType = passedItemType.GetGenericArguments()[0]; 
      pInfoOut = itemType.GetProperty(passedProperty); 
     } 
     else 
     { 
      pInfoOut = passedItemType.GetProperty(passedProperty); 
     } 

     return pInfoOut; 
    } 

目前这符合我的要求,因为他们的今天,我已经具有以下属性,列表,子类的子类进行了测试与列表等。到4级深,但应该正常工作,无论深度:

  • 的firstName
  • lastName的
  • 项目[1]。链轮
  • subClass.subClassInt
  • subClass.mySubClassObj.sprocketObj
  • subClass.ItemsInMySubClass [1] .sprocket
  • subClass.ItemsInMySubClass [0] .mySubClassObj.widgetObj
  • subClass.ItemsInMySubClass [2] .mySubClassObj .sprocketObj

如果任何人有更好的解决方案,或看到我有什么潜在的问题,我欢迎反馈意见。

0

你的情况最好的办法是做一个分解器来分割表达式。

+0

你有一个工作的例子吗?分割很容易'string [] parts = key.Split('。');'其余的动态地向下钻取,检测类型(如果是列表,是什么)以及获取这些属性等。那是棘手的部分。 –

+0

没有。基本思想是你遍历零件并处理零件。如果零件包含'['或不包含,我会分割。如果包含则处理索引器,如果不是,则要简单得多。我宁愿不打扰索引器,并使用列表的通用类型。 –

+0

感谢彼得,我有“基本想法”,我寻找一种通用的“最佳方法”,不需要使用一系列嵌套for循环/ linq。我想这肯定是以前做过的事情。 –