2010-10-05 27 views
0

我想創建對象的屬性列表。我可以爲基本對象創建一個列表,但是如果我有一種情況,即類型對象A包含一個類型爲對象B的屬性,其中包含類型爲對象A ...的屬性,那麼我會得到無限遞歸。 我所做的是爲所有名爲「RecursivePropertyList」的對象添加一個靜態屬性,這是每個遞歸屬性的List<string>創建屬性樹的函數?

因此,例如: 我有一個Person類與屬性Vendor類型VendorVendor班級有一個名爲People的房產,類型爲List<Person>

Person class I中,將RecursivePropertyList的值設置爲myList.Add("Vendor.People")。 在Vendor班中,我將RecursivePropertyList的值設置爲myList.Add("People.Vendor")

然後在創建屬性列表的函數中,我檢查當前的objectname.propertyName是否在RecursivePropertyList中,如果是這樣,我不會將其添加到屬性列表中,也不會深入到它獲得它的屬性。

這在上述情況下效果很好。

但是,當我遇到以下情況時,它開始失敗: Application類別的屬性類型爲List<ApplicationFunction_Application>ApplicationFunction類有一個List<ApplicationFunction_Application>類型的屬性。 ApplicationFunction_Application類有兩個屬性,Application類型之一,另一種類型ApplicationFunctionApplicationFunction_Application課程的目的是定義ApplicationApplicationFunction之間的多對多關係。

ApplicationRecursivePropertyList我把:

myList.Add("ApplicationFunctions.Application");

ApplicationFunctionRecursivePropertyList我把:

myList.Add("Applications.ApplicationFunction");

ApplicationFunction_ApplicationRecursivePropertyList我把:

myList.Add("ApplicationFunction.Applications");

myList.Add("Application.ApplicationFunctions");

但是,我的劇本只是不斷無休止的循環下去,永不停止。

這裏是函數使用的代碼:

首先,被稱爲是開始整個事情的功能:

public static EquatableList<PropertyState> FillPropertyStateList(System.Type myObjectType, ref EquatableList<PropertyState> myPropertyStateList) 
     { 
      List<string> myRecursivePropertyList = FillDefaultRecursivePropertyList(myObjectType); 
      return FillPropertyStateList(myObjectType, ref myPropertyStateList, string.Empty, string.Empty, myRecursivePropertyList); 
     } 

然後,做的工作,並調用肉功能本身遞歸地爲所有子對象生成屬性列表。

public static EquatableList<PropertyState> FillPropertyStateList(System.Type myObjectType, ref EquatableList<PropertyState> myPropertyStateList, string myParentPrefix, string myObjectName, List<string> myRecursivePropertyList) 
     { 
      if (myPropertyStateList == null) 
      { 
       myPropertyStateList = new EquatableList<PropertyState>(); 
      } 
      if (string.IsNullOrEmpty(myParentPrefix)) 
      { 
       myParentPrefix = string.Empty; 
      } 
      else if (!myParentPrefix.EndsWith(".")) 
      { 
       myParentPrefix = myParentPrefix + "."; 
      } 
      if (string.IsNullOrEmpty(myObjectName)) 
      { 
       myObjectName = string.Empty; 
      } 
      else 
      { 
       myObjectName = myObjectName + "."; 
      } 

      foreach (System.Reflection.PropertyInfo info in myObjectType.GetProperties()) 
      { 
       if (info.PropertyType.BaseType == typeof(BOBase)) 
       { 
        if (!myRecursivePropertyList.Exists(delegate(string x) { return x.Equals(myObjectName + info.Name); })) 
        { 
         myPropertyStateList.Add(new PropertyState(myParentPrefix + myObjectName + info.Name, true, PropertyType.BOBase)); 
         List<string> myChildRecursivePropertyList = FillDefaultRecursivePropertyList(info.PropertyType); 
         myChildRecursivePropertyList.AddRange(myRecursivePropertyList.FindAll(delegate(string x) { return Regex.IsMatch(x, info.Name + ".*"); })); 
         FillPropertyStateList(info.PropertyType, ref myPropertyStateList, myParentPrefix + myObjectName, info.Name, myChildRecursivePropertyList); 
        } 
       } 
       else if (info.PropertyType.IsGenericType 
        && (info.PropertyType.BaseType.GetGenericTypeDefinition() == typeof(List<>) || info.PropertyType.BaseType.GetGenericTypeDefinition() == typeof(Library.EquatableList<>))) 
       { 
        if (!myRecursivePropertyList.Exists(delegate(string x) { return x.Equals(myObjectName + info.Name); })) 
        { 
         myPropertyStateList.Add(new PropertyState(myParentPrefix + myObjectName + info.Name, true, PropertyType.BOBaseCollection)); 
         List<string> myChildRecursivePropertyList = FillDefaultRecursivePropertyList(info.PropertyType.BaseType.GetGenericArguments()[0]); 
         myChildRecursivePropertyList.AddRange(myRecursivePropertyList.FindAll(delegate(string x) { return Regex.IsMatch(x, info.Name + ".*"); })); 
         FillPropertyStateList(info.PropertyType.BaseType.GetGenericArguments()[0], ref myPropertyStateList, myParentPrefix + myObjectName, info.Name, myChildRecursivePropertyList); 
        } 
       } 
       else 
       { 
        myPropertyStateList.Add(new PropertyState(myParentPrefix + myObjectName + info.Name, true, PropertyType.Standard)); 
       } 

      } 
      return myPropertyStateList; 
     } 

的輔助函數得到默認的遞歸屬性列表:什麼我做錯了

private static List<string> FillDefaultRecursivePropertyList(System.Type myObjectType) 
    { 
     List<string> myRecursivePropertyList = new List<string>(); 
     if (myObjectType.BaseType == typeof(BOBase)) 
     { 
      System.Reflection.PropertyInfo pi = myObjectType.GetProperty("RecursivePropertyList", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); 
      if (pi != null) 
      { 
       myRecursivePropertyList = (List<string>)pi.GetValue(null, null); 
      } 
     } 
     return myRecursivePropertyList; 
    } 

任何想法?

+0

爲什麼你需要這個?我的第一本能是,無論你想實現什麼,都有一個更好的方法,但是因爲我不知道你想達到什麼目的,所以我不能提出任何建議。 – Timwi 2010-10-05 20:58:49

+0

另外,你爲什麼不使用調試器?它可以確切地告訴你無限遞歸發生的位置,它可以讓你逐步找出錯誤發生的位置。 – Timwi 2010-10-05 21:00:42

+0

我需要列表的原因如下。我想能夠指定要實例化對象的哪些屬性。我的對象的某些屬性需要第二次訪問數據庫以獲取更多數據,有時我實際上並不需要這些數據。所以我想能夠設置不應該被實例化的屬性。爲了做到這一點,我需要一個具有bool flg值的屬性列表,以確定該屬性是否應該被「填充」。希望這是有道理的?如果有更好的辦法達到這個目標,我就會全神貫注。 =) – 2010-10-05 22:59:28

回答

0

我還沒有深入研究代碼,但是,您是否考慮過使用Attribute來表示哪些屬性是遞歸的?這可以爲您節省不得不維護單獨的靜態屬性列表的麻煩。似乎列表方法可能容易出現潛在的困難同步問題。

ETA:示例代碼:

如果我正確理解這一點,像這樣的probbaly一個屬性級屬性的工作。它包含一個幫助器方法,用於從給定類型中檢索標記爲遞歸的屬性,這可能在構建樹時有所幫助。

[AttributeUsage(AttributeTargets.Property)] 
public class RecursivePropertyAttribute 
    : Attribute 
{ 
    private static Dictionary<Type, List<PropertyInfo>> _Cache = new Dictionary<Type, List<PropertyInfo>>(); 

    public IEnumerable<PropertyInfo> GetRecursiveProperties(Type t) 
    { 
     // Check the cache for the type 
     if (!_Cache.ContainsKey(t)) 
     { 
      // Create the entry 
      _Cache.Add(t, new List<PropertyInfo>()); 

      // Add properties that have the attribute 
      foreach (PropertyInfo p in t.GetProperties()) 
      { 
       if (p.IsDefined(typeof(RecursivePropertyAttribute), true)) 
        _Cache[t].Add(p); 
      } 
     } 

     return _Cache[t]; 
    } 
} 
+0

與此相關的問題是屬性在其自己的類中未被確定爲遞歸。例如,Person的Vendor屬性本身不是遞歸屬性,但Vendor對象的People屬性中的Person對象的Vendor屬性是遞歸的......這有意義嗎?所以我需要能夠從父實例化類設置「子」ckasses的遞歸屬性。 – 2010-10-05 23:01:33

+0

在閱讀您對上述文章的評論後,我認爲我更瞭解您的問題。如果潛在的「遞歸」屬性相當有限,那麼重載ctors是否有意義?在你引用的例子中,像Vendor()和Vender(Person)這樣的東西允許你用提供的參數預先填充屬性值,或者在需要的時候將它留空以便加載延遲? – Steven 2010-10-06 12:56:55

+0

除非我誤解了你的場景(我很可能是這樣),否則屬性的遞歸是否依賴於事件鏈與列表的靜態特性相沖突?這可能是問題嗎?或者列表只是潛在的遞歸屬性的定義? – Steven 2010-10-06 13:02:09