Tôi đã kết thúc việc tìm hiểu sâu hơn về xử lý đối tượng chung và thấy cách này phức tạp hơn bất kỳ giả định ban đầu nào. Đây là phương pháp bây giờ tôi đang sử dụng:
/// <summary>Check whether the specified type is enumerable.</summary>
/// <param name="type">The type.</param>
/// <param name="underlyingType">IEnumerable{int} would be int</param>
/// <param name="excludeString">
/// [OPTIONAL] if set to <c>true</c> [exclude string]. Strings are enumerable as char[]
/// this is likely not something you want. Default is true (string will return false)
/// </param>
/// <returns><c>true</c> supplied type is enumerable otherwise <c>false</c></returns>
public static bool IsEnumerable(this Type type, out Type underlyingType,
bool excludeString = true)
{
underlyingType = null;
if (type.IsEnum || type.IsPrimitive || type.IsValueType) return false;
if (excludeString && type == typeof(string)) return false;
if (type.IsGenericType)
{
if (type.IsTypeDefinitionEnumerable() ||
type.GetInterfaces()
.Any(t => t.IsSelfEnumerable() || t.IsTypeDefinitionEnumerable()))
{
underlyingType = type.GetGenericArguments()[0];
return true;
}
}
//direct implementations of IEnumerable<T>, inheritance from List<T> etc
var enumerableOrNull = type.GetInterfaces()
.FirstOrDefault(t => t.IsTypeDefinitionEnumerable());
if (enumerableOrNull == null) return false;
underlyingType = enumerableOrNull.GetGenericArguments()[0];
return true;
}
//
private static bool IsSelfEnumerable(this Type type)
{
bool isDirectly = type == typeof(IEnumerable<>);
return isDirectly;
}
private static bool IsTypeDefinitionEnumerable(this Type type)
{
bool isViaInterfaces = type.IsGenericType &&
type.GetGenericTypeDefinition().IsSelfEnumerable();
return isViaInterfaces;
}
Giải pháp này được thử nghiệm:
Install-Package NUnit -version 2.6.4
Gói cài đặt nên
[Test]
public void List_is_enumerable()
{
var sut = new List<int>();
Type underlyingType;
var result = sut.IsEnumerable(out underlyingType);
result.ShouldBeTrue();
underlyingType.ShouldBe(typeof(int));
}
//
[Test]
public void Yield_return_is_enumerable()
{
var sut = Yielded();
Type underlyingType;
var result = sut.IsEnumerable(out underlyingType);
result.ShouldBeTrue();
underlyingType.ShouldBe(typeof(int));
}
private IEnumerable<int> Yielded()
{
for (int i = 0; i < 3; i++)
{
yield return i;
}
}
//
[Test]
public void int_is_not_an_enumerable()
{
var sut = 5;
Type underlyingType;
var result = sut.IsEnumerable(out underlyingType);
result.ShouldBe(false);
underlyingType.ShouldBeNull();
}
[Test]
public void object_is_not_an_enumerable()
{
var sut = new { foo = 1};
Type underlyingType;
var result = sut.IsEnumerable(out underlyingType);
result.ShouldBe(false);
underlyingType.ShouldBeNull();
}
giữ cho hậu thế. Điều này không trả lời câu hỏi ban đầu nhưng rõ ràng là hữu ích cho các thành viên ở đây.
public static bool IsA<T>(this Type type)
{
return typeof (T).IsAssignableFrom(type);
}
Nguồn
2010-02-23 16:03:05
Tôi nghĩ rằng giải pháp Stan R. có lẽ là khoảng những gì bạn đang tìm kiếm, nhưng vấn đề của bạn là underspecified . Bạn chỉ quan tâm đến các loại chung chung hay bạn cũng có thể quan tâm đến các loại không chung chung (ví dụ: một loại không chung chung đang triển khai 'IEnumerable')? –
kvb
Tại buổi lễ, tôi chỉ quan tâm đến các loại chung chung, nhưng bạn có một điểm tốt. –