2009-10-30 26 views
11

Tôi đang cố gắng để phát hiện nếu một trường hợp đặc biệt của một đối tượng Type là một generic "IEnumerable" ...NET Reflection: Phát hiện IEnumerable <T>

Điều tốt nhất tôi có thể đưa ra là:

// theType might be typeof(IEnumerable<string>) for example... or it might not 
bool isGenericEnumerable = theType.GetGenericTypeDefinition() == typeof(IEnumerable<object>).GetGenericTypeDefinition() 
if(isGenericEnumerable) 
{ 
    Type enumType = theType.GetGenericArguments()[0]; 
    etc. ...// enumType is now typeof(string) 

Nhưng điều này có vẻ hơi gián tiếp - có cách trực tiếp/thanh lịch hơn để làm điều này không?

+0

vui lòng xem theo dõi của tôi: http://stackoverflow.com/questions/1650310/net-reflection-determining-whether-an-array-of-t-would-be-convertible-to-some-o –

Trả lời

22

Bạn có thể sử dụng

if(theType.IsGenericType && theType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) 
{ 
    Type underlyingType = theType.GetGenericArguments()[0]; 
    //do something here 
} 

EDIT: thêm việc kiểm tra IsGenericType, cảm ơn vì những ý kiến ​​hữu ích

+2

Đó là ass khá tệ, ngay tại đó. –

+2

nếu theType không phải là chung chung, nó sẽ ném một 'InvalidOperationException' - không phải là một giải pháp rất tốt cho một IMHO kiểm tra. – Lucero

+3

Điều này chỉ hoạt động nếu 'theType' là chính xác typeof (IEnumerable <>), không phải nếu loại thực hiện giao diện. Hy vọng rằng đó là những gì bạn đang sau. –

2

Lưu ý rằng bạn không thể gọi GetGenericTypeDefinition() trên một loại phi chung chung, do đó, kiểm tra đầu tiên với IsGenericType.

Tôi không chắc chắn liệu bạn có muốn kiểm tra xem loại có triển khai thực hiện chung IEnumerable<> hoặc nếu bạn muốn xem loại giao diện là IEnumerable<> hay không. Đối với trường hợp đầu tiên, sử dụng đoạn mã sau (kiểm tra bên trong với interfaceType là trường hợp thứ hai):

if (typeof(IEnumerable).IsAssignableFrom(type)) { 
    foreach (Type interfaceType in type.GetInterfaces()) { 
     if (interfaceType.IsGenericType && (interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))) { 
      Console.WriteLine("{0} implements {1} enumerator", type.FullName, interfaceType.FullName); // is a match 
     } 
    } 
} 
+0

là mã này đề cập đến giao diện IEnumerable cũ (không chung)? –

+0

Tôi sẽ làm rõ câu hỏi của mình ... –

+0

Có, bởi vì cái chung chung ngụ ý cái không chung chung, đó là kiểm tra nhanh để đảm bảo rằng nó đáng để đi qua các giao diện. Nếu 'IEnumerable' (không chung chung) không được thực hiện,' IEnumerable <> '(generic) không thể là một trong hai. – Lucero

4

Bạn có thể sử dụng đoạn mã này để xác định xem một loại hình cụ thể thực hiện các giao diện IEnumerable<T>.

Type type = typeof(ICollection<string>); 

bool isEnumerable = type.GetInterfaces()  // Get all interfaces. 
    .Where(i => i.IsGenericType)    // Filter to only generic. 
    .Select(i => i.GetGenericTypeDefinition()) // Get their generic def. 
    .Where(i => i == typeof(IEnumerable<>)) // Get those which match. 
    .Count() > 0; 

Nó sẽ làm việc cho bất kỳ giao diện, tuy nhiên nó sẽ không việc nếu loại bạn vượt qua trong là IEnumerable<T>.

Bạn sẽ có thể sửa đổi nó để kiểm tra các đối số loại được truyền cho mỗi giao diện.

+0

Thay vì ở đâu(). Count() bạn có thể sử dụng Bất kỳ(). – Fred

Các vấn đề liên quan