2013-08-02 59 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。我想這肯定是以前做過的事情。 –