2009-12-01 61 views
5

我正在C#中的遊戲引擎工作。我正在使用的課程名爲CEntityRegistry,其工作是跟蹤遊戲中CEntity的許多實例。我的目標是能夠使用給定類型查詢CEntityRegistry,並獲得該類型的每個CEntity的列表。給定一個C#類型,獲取其基類和實現的接口

我今天準備這樣做,因此,爲保持地圖:正是如此

private IDictionary<Type, HashSet<CEntity>> m_TypeToEntitySet; 

並更新註冊表:

private void m_UpdateEntityList() 
     { 
      foreach (CEntity theEntity in m_EntitiesToRemove.dequeueAll()) 
      { 
       foreach (HashSet<CEntity> set in m_TypeToEntitySet.Values) 
       { 
        if (set.Contains(theEntity)) 
         set.Remove(theEntity); 
       } 
      } 
      foreach (CEntity theEntity in m_EntitiesToAdd.dequeueAll()) 
      { 
       Type entityType = theEntity.GetType(); 
       foreach (Type baseClass in entityType.GetAllBaseClassesAndInterfaces()) 
        m_TypeToEntitySet[baseClass].Add(theEntity); 

      } 
     } 

我的問題是,有沒有功能Type.GetAllBaseClassesAndInterfaces - 我怎麼去寫它?

+0

,但肯定不希望一個類型的實例被計爲一個實例的所有它的子類型和接口呢? – 2009-12-01 02:40:56

+0

顯然他有。 – SLaks 2009-12-01 02:45:55

+2

您是否認爲使用Type.IsAssignableFrom(Type)可能會使您的生活比試圖映射每個CEntity的整個繼承層次結構更簡單?不知道您究竟打算如何使用存儲庫,但可能需要考慮一下。 – Rory 2009-12-01 02:48:51

回答

7

類型有一個屬性BASETYPE和方法FindInterfaces。

https://msdn.microsoft.com/en-us/library/system.type.aspx

因此,實際上,它幾乎擁有Type.GetAllBaseClassesAndInterfaces,但你必須兩次調用,而不是一個。

+0

他想通過類型層次遞歸(因此GetAllBaseClass ** es **),所以並不那麼簡單。 – SLaks 2009-12-01 02:42:10

+1

我想我不確定他的問題是關於使用什麼方法/屬性,或者如何編寫將遍歷繼承樹的函數。我曾假設前者。 – 2009-12-01 02:44:17

+0

將CEntity構造函數註冊爲該字典可能會更簡單。然後,您不必爲每個對象查詢繼承樹。大量使用反射往往表明設計出現問題。 – 2009-12-01 02:52:42

14

你可以寫一個擴展方法是這樣的:

public static IEnumerable<Type> GetBaseTypes(this Type type) { 
    if(type.BaseType == null) return type.GetInterfaces(); 

    return Enumerable.Repeat(type.BaseType, 1) 
        .Concat(type.GetInterfaces()) 
        .Concat(type.GetInterfaces().SelectMany<Type, Type>(GetBaseTypes)) 
        .Concat(type.BaseType.GetBaseTypes()); 
} 
+0

說我有 「類中的一個:卓智{}」 「類兩種:一種{}」 書面,對typeof運算(二).GetBaseTypes運行()將返回伊俄涅倍數,即使它只是實現一旦。兩個是IOne,所以即使它沒有明確實現它也會返回它。 – claudekennilol 2014-05-08 18:31:33

+0

@claudekennilol:然後添加'.Distinct()'。另見http://blogs.msdn.com/b/ericlippert/archive/2011/04/04/so-many-interfaces.aspx和http://blogs.msdn.com/b/ericlippert/archive/2011/ 12/08/so-many-interfaces-part-two.aspx – SLaks 2014-05-08 19:31:39

+0

OMFG!這是一些嚴肅優雅的代碼!非常好。 – 2016-08-25 06:59:57

1

使用此代碼:

Func<Type, List<Type>> f = ty => 
{ 
    var tysReturn = new List<Type>(); 
    if (ty.BaseType != null) 
    { 
     tysReturn.Add(ty.BaseType); 
    } 
    tysReturn.AddRange(ty.GetInterfaces()); 
    return tysReturn; 
}; 

功能f將採取類型和返回的基本類型以及接口的列表。

希望它有幫助。

5

基於一個從SLaks更細緻的回答會是:

public static IEnumerable<Type> GetBaseClassesAndInterfaces(this Type type) 
{ 
    return type.BaseType == typeof(object) 
     ? type.GetInterfaces() 
     : Enumerable 
      .Repeat(type.BaseType, 1) 
      .Concat(type.GetInterfaces()) 
      .Concat(type.BaseType.GetBaseClassesAndInterfaces()) 
      .Distinct(); 
} 
相關問題