답변:
IEnumerable<T> myEnumerable;
Type type = myEnumerable.GetType().GetGenericArguments()[0];
따라서
IEnumerable<string> strings = new List<string>();
Console.WriteLine(strings.GetType().GetGenericArguments()[0]);
인쇄합니다 System.String
.
.NET 용 MSDN 을 참조하십시오 Type.GetGenericArguments
.
편집 : 이것이 의견의 우려를 해결할 것이라고 믿습니다.
// returns an enumeration of T where o : IEnumerable<T>
public IEnumerable<Type> GetGenericIEnumerables(object o) {
return o.GetType()
.GetInterfaces()
.Where(t => t.IsGenericType
&& t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.Select(t => t.GetGenericArguments()[0]);
}
일부 객체는 둘 이상의 제네릭을 구현 IEnumerable
하므로 열거를 반환해야합니다.
편집 : 비록, 나는 IEnumerable<T>
하나 이상의 클래스를 구현하는 것은 끔찍한 아이디어입니다 T
.
나는 확장 방법을 만들 것입니다. 이것은 내가 던진 모든 것과 함께 작동했습니다.
public static Type GetItemType<T>(this IEnumerable<T> enumerable)
{
return typeof(T);
}
비슷한 문제가있었습니다. 선택한 답변은 실제 인스턴스에 적용됩니다. 제 경우에는 (에서 PropertyInfo
) 유형 만있었습니다 .
유형 자체가 typeof(IEnumerable<T>)
의 구현 이 아닌 경우 선택한 답변이 실패합니다 IEnumerable<T>
.
이 경우 다음이 작동합니다.
public static Type GetAnyElementType(Type type)
{
// Type is Array
// short-circuit if you expect lots of arrays
if (type.IsArray)
return type.GetElementType();
// type is IEnumerable<T>;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (IEnumerable<>))
return type.GetGenericArguments()[0];
// type implements/extends IEnumerable<T>;
var enumType = type.GetInterfaces()
.Where(t => t.IsGenericType &&
t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.Select(t => t.GenericTypeArguments[0]).FirstOrDefault();
return enumType ?? type;
}
Type.GenericTypeArguments
-dotNet FrameWork 버전> = 4.5에만 해당됩니다. 그렇지 않으면 Type.GetGenericArguments
대신 사용하십시오.
IEnumerable<T>
(제네릭을 통해) 알고 있으면 typeof(T)
작동합니다. 그렇지 않으면 ( object
또는 비 제네릭 IEnumerable
) 구현 된 인터페이스를 확인하십시오.
object obj = new string[] { "abc", "def" };
Type type = null;
foreach (Type iType in obj.GetType().GetInterfaces())
{
if (iType.IsGenericType && iType.GetGenericTypeDefinition()
== typeof(IEnumerable<>))
{
type = iType.GetGenericArguments()[0];
break;
}
}
if (type != null) Console.WriteLine(type);
Type type
매개 변수가 아닌 object obj
매개 변수 : 당신은 그냥 대체 할 수 obj.GetType()
와 type
당신이 통과하면 때문에 typeof(IEnumerable<T>)
당신은 아무것도 얻을 수 없다. 이 문제를 해결하려면 type
자체를 테스트하여 제네릭인지 확인한 IEnumerable<>
다음 해당 인터페이스를 확인하십시오.
토론 해 주셔서 대단히 감사합니다. 나는 그것을 아래 솔루션의 기초로 사용했는데, 이는 나에게 관심이있는 모든 경우 (IEnumerable, 파생 클래스 등)에서 잘 작동합니다. 누군가가 필요로 할 경우를 대비하여 여기에 공유해야한다고 생각했습니다.
Type GetItemType(object someCollection)
{
var type = someCollection.GetType();
var ienum = type.GetInterface(typeof(IEnumerable<>).Name);
return ienum != null
? ienum.GetGenericArguments()[0]
: null;
}
someCollection.GetType().GetInterface(typeof(IEnumerable<>).Name)?.GetGenericArguments()?.FirstOrDefault()
대신에 IEnumerable<T>
또는 T
메모 사용이 될 더 간단한 상황에 대한 대안 GenericTypeArguments
입니다 GetGenericArguments()
.
Type inputType = o.GetType();
Type genericType;
if ((inputType.Name.StartsWith("IEnumerable"))
&& ((genericType = inputType.GenericTypeArguments.FirstOrDefault()) != null)) {
return genericType;
} else {
return inputType;
}
이것은 IEnumerable<>
유형이 상속 트리의 모든 수준에서 작동한다는 점에서 Eli Algranti의 솔루션을 개선 한 것 입니다.
이 솔루션은 모든 Type
. 유형이가 아닌 경우 IEnumerable<>
전달 된 유형을 반환합니다. 객체의 경우를 사용 GetType
합니다. 유형의 경우을 사용한 typeof
다음 결과에서이 확장 메서드를 호출합니다.
public static Type GetGenericElementType(this Type type)
{
// Short-circuit for Array types
if (typeof(Array).IsAssignableFrom(type))
{
return type.GetElementType();
}
while (true)
{
// Type is IEnumerable<T>
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
return type.GetGenericArguments().First();
}
// Type implements/extends IEnumerable<T>
Type elementType = (from subType in type.GetInterfaces()
let retType = subType.GetGenericElementType()
where retType != subType
select retType).FirstOrDefault();
if (elementType != null)
{
return elementType;
}
if (type.BaseType == null)
{
return type;
}
type = type.BaseType;
}
}
나는 이것이 조금 오래되었다는 것을 알고 있지만이 방법이 의견에 명시된 모든 문제와 도전을 다룰 것이라고 믿습니다. 내 작업에 영감을 준 Eli Algranti에게 감사드립니다.
/// <summary>Finds the type of the element of a type. Returns null if this type does not enumerate.</summary>
/// <param name="type">The type to check.</param>
/// <returns>The element type, if found; otherwise, <see langword="null"/>.</returns>
public static Type FindElementType(this Type type)
{
if (type.IsArray)
return type.GetElementType();
// type is IEnumerable<T>;
if (ImplIEnumT(type))
return type.GetGenericArguments().First();
// type implements/extends IEnumerable<T>;
var enumType = type.GetInterfaces().Where(ImplIEnumT).Select(t => t.GetGenericArguments().First()).FirstOrDefault();
if (enumType != null)
return enumType;
// type is IEnumerable
if (IsIEnum(type) || type.GetInterfaces().Any(IsIEnum))
return typeof(object);
return null;
bool IsIEnum(Type t) => t == typeof(System.Collections.IEnumerable);
bool ImplIEnumT(Type t) => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>);
}
public static Type GetInnerGenericType(this Type type)
{
// Attempt to get the inner generic type
Type innerType = type.GetGenericArguments().FirstOrDefault();
// Recursively call this function until no inner type is found
return innerType is null ? type : innerType.GetInnerGenericType();
}
이것은 내부 제네릭 유형이없는 구체적인 유형 정의를 얻을 때까지 제네릭 유형 목록 아래로 먼저 깊이 이동하는 재귀 함수입니다.
이 유형으로이 방법을 테스트했습니다.
ICollection<IEnumerable<ICollection<ICollection<IEnumerable<IList<ICollection<IEnumerable<IActionResult>>>>>>>>
반환해야하는 IActionResult
typeof(IEnumerable<Foo>)
. 첫 번째 일반 인수 (이 경우)를 반환합니다 .GetGenericArguments()
[0]
typeof(Foo)
다음은 읽을 수없는 Linq 쿼리 표현식 버전입니다.
public static Type GetEnumerableType(this Type t) {
return !typeof(IEnumerable).IsAssignableFrom(t) ? null : (
from it in (new[] { t }).Concat(t.GetInterfaces())
where it.IsGenericType
where typeof(IEnumerable<>)==it.GetGenericTypeDefinition()
from x in it.GetGenericArguments() // x represents the unknown
let b = it.IsConstructedGenericType // b stand for boolean
select b ? x : x.BaseType).FirstOrDefault()??typeof(object);
}
메서드는 또한 비 제네릭 IEnumerable
을 고려합니다 object
.이 경우 Type
에는 구체적인 인스턴스 가 아닌 인수를 사용 하기 때문에 반환 됩니다 . 그건 그렇고, x가 알려지지 않은 것을 나타 내기 때문에이 비디오 는 무관하지만 흥미 롭다는 것을 알았 습니다 ..