我正在使用C#中的游戏引擎。我正在处理的课程称为CEntityRegistry
,其工作是跟踪游戏中CEntity
的许多实例。我的目标是能够使用给定类型查询CEntityRegistry
,并获取该类型的每个CEntity
的列表。
因此,我想做的是维护地图:
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 :(得分:17)
您可以编写如下的扩展方法:
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());
}
答案 1 :(得分:8)
Type有一个属性BaseType和一个FindInterfaces方法。
https://msdn.microsoft.com/en-us/library/system.type.aspx
实际上,它几乎有Type.GetAllBaseClassesAndInterfaces
,但您必须拨打两个电话而不是一个电话。
答案 2 :(得分:6)
基于来自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();
}
答案 3 :(得分: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
将接受一个Type并返回其基类型和接口的列表。
希望它有所帮助。
答案 4 :(得分:1)
这里。先前的答案有问题。 另外,此答案不需要“不同”。这些值已经不同。而且这个效率更高。
public static IEnumerable<Type> GetBaseTypes(this Type type, bool bIncludeInterfaces = false)
{
if (type == null)
yield break;
for (var nextType = type.BaseType; nextType != null; nextType = nextType.BaseType)
yield return nextType;
if (!bIncludeInterfaces)
yield break;
foreach (var i in type.GetInterfaces())
yield return i;
}