2009-12-01 9 views
5

Pracuję na silniku gry w języku C#. Klasa, nad którą pracuję nazywa się CEntityRegistry, a jej zadaniem jest śledzenie wielu wystąpień CEntity w grze. Moim celem jest umożliwienie przeskanowania CEntityRegistry z danym typem i uzyskanie listy każdego z tych CEntity tego typu.Biorąc pod uwagę typ C#, Zdobądź jego klasy bazowe i implementuj interfejsy

Co chciałbym zrobić, jest więc utrzymanie mapę:

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

i aktualizuje rejestr wygląda następująco:

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); 

      } 
     } 

Problem mam to, że nie ma funkcji Type.GetAllBaseClassesAndInterfaces - Jak mam to napisać?

+0

ale na pewno nie chcesz instancją typu należy zaliczyć jako przykład wszystko to podtypy i interfejsy, jak również? –

+0

Najwyraźniej tak. – SLaks

+2

Czy uważałeś, że użycie Type.IsAssignableFrom (Type) może uczynić twoje życie nieco prostszym, niż próba mapowania całej hierarchii dziedziczenia każdej CEntity? Nie wiesz dokładnie, jak dokładnie zamierzasz korzystać z repozytorium, ale może być na co popatrzeć. – Rory

Odpowiedz

7

Type ma BaseType nieruchomości i metoda A FindInterfaces.

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

Tak właściwie to prawie ma Type.GetAllBaseClassesAndInterfaces, ale trzeba zrobić dwa połączenia zamiast jednego.

+0

Chce się powtarzać poprzez hierarchię typów (stąd GetAllBaseClass ** es **), więc nie jest to takie proste. – SLaks

+1

Chyba nie jestem pewien, czy jego pytanie dotyczyło jakiej metody/właściwości używać, lub jak napisać funkcję, która będzie przechodzić przez drzewo dziedziczenia. Przyjąłem to pierwsze. –

+0

Łatwiejsze może być skonstruowanie konstruktora CEntity w tym słowniku. Wtedy nie musisz wyszukiwać drzewa dziedziczenia dla każdego obiektu. Intensywne korzystanie z refleksji często świadczy o tym, że coś jest nie tak z twoim projektem. –

14

można napisać metodę rozszerzenia tak:

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

Say mam „klasa pierwsza: IONE {}” „klasa druga: Jeden {}” Jak napisano, prowadzony przeciwko typeof (dwa) .GetBaseTypes() zwróci wielokrotności IONE mimo to realizowane tylko pewnego razu. Two to IOne, więc zwraca je, nawet jeśli nie zostało to jednoznacznie zaimplementowane. – claudekennilol

+0

@ claudekennilol: Następnie dodaj '.Distinct()'. Zobacz także http://blogs.msdn.com/b/ericlippert/archive/2011/04/04/so-many-interfaces.aspx i http://blogs.msdn.com/b/ericlippert/archive/2011/ 12/08/so-many-interfaces-part-two.aspx – SLaks

+0

OMFG! To jest jakiś poważnie elegancki kod! Bardzo dobrze. –

1

użyć tego kodu:

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; 
}; 

Funkcja f zajmie Rodzaj i zwróci listę tego typu bazowej powiększonej interfejsów.

Mam nadzieję, że to pomaga.

5

bardziej wyrafinowane rozwiązanie oparte na jednym z SLaks byłoby:

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(); 
} 
Powiązane problemy