2009-12-01 17 views
5

私はC#のゲームエンジンで作業しています。私が取り組んでいるクラスはCEntityRegistryと呼ばれ、その仕事はゲーム内の多くの場合CEntityを追跡することです。私の目標は、特定のタイプのCEntityRegistryを照会し、そのタイプの各CEntityのリストを取得できるようにすることです。私がやりたいのは何C#の型を指定すると、その基底クラスと実装されたインターフェイスを取得します。

は、そのため、マップを維持している:私が持っている問題は、機能がないということである

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

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

そしてthuslyレジストリを更新します - どうやってそれを書くの?

+0

、しかし確実に、あなたはすべてのそれは同様のサブタイプとインターフェイスの型のインスタンスは、インスタンスとしてとしてカウントされるようにしたくないですか? –

+0

明らかに彼はそうです。 – SLaks

+2

Type.IsAssignableFrom(Type)を使用すると、すべてのCEntityの継承階層全体をマップしようとするより簡単になります。リポジトリの使用方法を正確にどのように正確に計画しているのかはっきりしていませんが、見るべきことかもしれません。 – Rory

答えて

7

タイプは、プロパティBaseTypeとメソッドFindInterfacesを持っています。

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

だから実際には、それはほとんどType.GetAllBaseClassesAndInterfacesを持っている、しかし、あなたは1つではなく、2つの呼び出しを行う必要があります。

+0

彼はタイプ階層(したがってGetAllBaseClass ** es **)を再帰したいので、それは簡単ではありません。 – SLaks

+1

私は彼の質問がどのメソッド/プロパティを使うべきか、あるいは継承ツリーをたどる関数を書く方法かどうかは分かりません。私は前者を前提としていた。 –

+0

CEntityコンストラクタをその辞書に登録するほうが簡単かもしれません。次に、各オブジェクトの継承ツリーを照会する必要はありません。リフレクションを頻繁に使用することは、デザインに何か問題があることを示す場合があります。 –

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

は「クラスワン:ジオン{}」私は を持っていると言う 「クラス2:ワン{}」typeof演算(二).GetBaseTypes(に対して実行書かれたよう は、)それが唯一の実装だにもかかわらず、ジオンの倍数を返します。一度。 2つはIOneなので、明示的に実装していなくても返します。 – claudekennilol

+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

+0

OMFG!これは真剣に優雅なコードです!非常に素晴らしい。 –

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を取ると、その基本型プラスインターフェイスのリストを返します。

希望します。 SLaksから1に基づいて

5

より洗練された答えは次のようになります。

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(); 
} 
関連する問題