2009-12-01 37 views
5

Tôi đang làm việc trên một cỗ máy trò chơi trong C#. Lớp tôi đang làm được gọi là CEntityRegistry và công việc của nó là theo dõi nhiều phiên bản của CEntity trong trò chơi. Mục tiêu của tôi là có thể truy vấn CEntityRegistry với một loại nhất định và nhận danh sách của mỗi loại CEntity loại đó.Đưa ra Loại C#, Nhận các Lớp cơ sở của nó và Giao diện Thực hiện

Những gì tôi muốn làm, do đó, là duy trì một bản đồ:

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

Và cập nhật registry thusly:

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

      } 
     } 

Tôi có vấn đề là không có chức năng Type.GetAllBaseClassesAndInterfaces - Làm thế nào tôi sẽ viết về nó?

+0

nhưng chắc chắn bạn không muốn một thể hiện của một loại để được tính là như một thể hiện tất cả những gì là tiểu chủng loại và giao diện không? –

+0

Dường như anh ấy làm. – SLaks

+2

Bạn có nghĩ rằng việc sử dụng Type.IsAssignableFrom (Type) có thể làm cho cuộc sống của bạn đơn giản hơn một chút so với cố gắng ánh xạ toàn bộ hệ thống phân cấp thừa kế của mọi CEntity? Bạn không chắc chính xác bạn định sử dụng kho lưu trữ như thế nào, nhưng nó có thể là một cái gì đó để xem xét. – Rory

Trả lời

7

Loại có BaseType bất động sản và một phương pháp FindInterfaces.

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

Vì vậy, trên thực tế, nó hầu như không có Type.GetAllBaseClassesAndInterfaces, nhưng bạn cần phải thực hiện hai cuộc gọi thay vì một.

+0

Anh ấy muốn kiểm tra lại thông qua phân cấp kiểu (Do đó GetAllBaseClass ** es **), vì vậy nó không đơn giản như vậy. – SLaks

+1

Tôi đoán tôi không chắc liệu câu hỏi của anh ta là về phương pháp/thuộc tính nào cần sử dụng hay cách viết một hàm sẽ đi qua cây thừa kế. Tôi đã giả định trước đây. –

+0

Có thể đơn giản hơn để làm cho hàm tạo CEntity tự đăng ký bằng từ điển đó. Sau đó, bạn không phải truy vấn cây thừa kế cho từng đối tượng. Việc sử dụng phản xạ nặng thường là dấu hiệu cho thấy có điều gì đó không ổn với thiết kế của bạn. –

14

Bạn có thể viết một phương pháp mở rộng như thế này:

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

Nói rằng tôi đã có "lớp Một: ione {}" "lớp thứ hai: Một {}" Theo văn bản, chạy chống lại typeof (Hai) .GetBaseTypes() sẽ trả về bội số của ione mặc dù nó chỉ thực hiện Một lần. Hai là một IOne vì vậy nó trả về nó mặc dù nó không có nó được thực hiện một cách rõ ràng. – claudekennilol

+0

@claudekennilol: Sau đó thêm '.Distinct()'. Xem thêm http://blogs.msdn.com/b/ericlippert/archive/2011/04/04/so-many-interfaces.aspx và http://blogs.msdn.com/b/ericlippert/archive/2011/ 12/08/so-many-interfaces-part-two.aspx – SLaks

+0

OMFG! Đây là một số mã thanh lịch nghiêm túc! Rất đẹp. –

1

Sử dụng mã này:

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

Chức năng f sẽ mất một Loại và trả về một danh sách các loại hình cơ bản của nó cộng với giao diện.

Hy vọng điều đó sẽ hữu ích.

5

câu trả lời More tinh chế dựa trên một từ SLaks sẽ là:

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(); 
} 
Các vấn đề liên quan