2012-01-11 41 views
0

只有當屬性的類型從某個基類繼承時,我如何遞歸地獲取對象的所有屬性?只有當這些屬性從某些基類繼承時,我如何才能在C#中遞歸搜索屬性?

這是我的嘗試:

static IEnumerable<PropertyInfo> FindProperties(object objectTree, Type targetType) 
{ 
    if (objectTree.GetType().IsAssignableFrom(targetType)) 
    { 
     var properties = objectTree.GetType().GetProperties(); 
     foreach (var property in properties) 
     { 
      yield return property; 
     } 

     foreach (var property in FindProperties(properties, targetType)) 
     { 
      yield return property; 
     } 
    } 
} 

所以我可以打電話,

var allPropertiesOfPageTypes = FindProperties(someClass, typeof(Page)); 

然而,返回的屬性的數量始終爲零。我究竟做錯了什麼?

編輯:

我不知道這事,但子類是通用類:

public abstract class MasterPage<T> : BasePage<T> where T : MasterPage<T> 

繼承:

public abstract class BasePage<T> : Page where T : BasePage<T> 

東西,從主/ BasePage的似乎繼承要返回虛假的IsAssignableFrom

+0

您是否嘗試過linq的'.OfType '? – 2012-01-11 08:17:41

+0

一秒鐘,我即將發佈我的嘗試.. – KingNestor 2012-01-11 08:19:18

+0

anatoliiG - 我認爲是因爲'OfType'給出了給定類型的對象,在這裏不適用 - 涉及的集合都有類型爲'PropertyInfo'的項目,例如? – 2012-01-11 08:46:33

回答

1

你需要時,你有正確的類型只遞歸,你需要一個實例,而不是物業本身:

static IEnumerable<PropertyInfo> FindProperties(object objectTree, Type targetType) 
{ 
    if (targetType.IsAssignableFrom(objectTree.GetType())) 
    { 
     var properties = objectTree.GetType().GetProperties(); 
     foreach (var property in properties) 
     { 
      yield return property; 

      if (targetType.IsAssignableFrom(property.PropertyType)) 
      { 
       object instance = property.GetValue(objectTree, null); 
       foreach (var subproperty in FindProperties(instance, targetType)) 
       { 
        yield return subproperty; 
       } 
      } 
     } 
    } 
} 
+0

現在,在調用此方法的方法中,我需要獲取該值,但不再有它來自的對象。任何想法如何保留它來自的對象,所以當我將propInfo.GetValue(page,null)作爲TElement時,它不會'爆炸? – KingNestor 2012-01-11 09:25:32

+0

@KingNestor - 無論如何我會返回值(使這個'IEnumerable '),並且如果您需要可以從'TElement'賦值的屬性類型,那麼您應該檢查屬性是否也返回該類型, typeof運算(TElement).IsAssignableFrom(subproperty.PropertyType)' – Keith 2012-01-11 10:50:13

0

也許這可能工作?

public static LinkedPageElement<TElement> GetLinkedElement<TPage, TElement>(Page page, bool verbose = true) where TElement : class 
{ 
    var propInfos = page.GetType().GetProperties(); 

    // First try to find the property in the current page type 
    foreach (var propInfo in propInfos) 
    { 
     var attributes = propInfo.GetCustomAttributes(typeof(LinkedPageAttribute), true); 
     if (attributes.Length == 0) continue; 

     var linkedPageAttribute = (from a in attributes where a.GetType() == typeof(LinkedPageAttribute) select a).FirstOrDefault(); 
     if (linkedPageAttribute == null || !(linkedPageAttribute is LinkedPageAttribute)) continue; 

     if ((linkedPageAttribute as LinkedPageAttribute).PageType == typeof(TPage)) 
     { 
      return new LinkedPageElement<TElement> 
      { 
       Element = propInfo.GetValue(page, null) as TElement, 
       AutoClick = (linkedPageAttribute as LinkedPageAttribute).AutoClick 
      }; 
     } 
    } 

    // Then try to find it in a property 
    var containedInProperty = propInfos.Where(x => x.PropertyType.IsSubclassOf(typeof(Page))) 
     .Select(x => GetLinkedElement<TPage, TElement>((Page)x.GetValue(page, null), false)) 
     .FirstOrDefault(x => x != null); 

    if (containedInProperty != null) return containedInProperty; 

    // you are trying to navigate to a page which cannot be reached from the current page, check to see you have a link with LinkedPage attribute 
    if (verbose) 
     throw new ArgumentException("You don't have a link to this page {0} from this page {1}".FormatWith(typeof(TPage), page.GetType())); 

    return null; 
} 
1

爲了驗證是否有物體從您有另一個類繼承做你正在做的事情正好相反:

if (targetType.IsAssignableFrom(objectTree.GetType())) 

這部作品以類似的方式:

Parent o = new Derived();