2009-12-01 57 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(); 
} 
相关问题