如何从泛型类或方法的成员获取T的类型?

时间:2022-07-10 16:05:59

Let say I have a generic member in a class or method, so:

假设我在类或方法中有一个泛型成员,那么:

public class Foo<T>
{
    public List<T> Bar { get; set; }

    public void Baz()
    {
        // get type of T
    }   
}

When I instantiate the class, the T becomes MyTypeObject1, so the class has a generic list property: List<MyTypeObject1>. The same applies to a generic method in a non-generic class:

当我实例化这个类时,T变成了MyTypeObject1,因此类具有一个泛型列表属性:list 。这同样适用于非泛型类中的泛型方法:

public class Foo
{
    public void Bar<T>()
    {
        var baz = new List<T>();

        // get type of T
    }
}

I would like to know, what type of objects the list of my class contains. So the list property called Bar or the local variable baz, contains what type of T?

我想知道,我的类列表包含什么类型的对象。list属性Bar或局部变量baz包含什么类型的T?

I cannot do Bar[0].GetType(), because the list might contain zero elements. How can I do it?

我不能执行Bar[0]. gettype(),因为列表可能包含零元素。我怎么做呢?

16 个解决方案

#1


546  

If I understand correctly, your list has the same type parameter as the container class itself. If this is the case, then:

如果我理解正确,您的列表具有与容器类本身相同的类型参数。如果是这样,则:

Type typeParameterType = typeof(T);

If you are in the lucky situation of having object as a type parameter, see Marc's answer.

如果您幸运地将对象作为类型参数,请参阅Marc的答案。

#2


452  

(note: I'm assuming that all you know is object or IList or similar, and that the list could be any type at runtime)

(注意:我假设您所知道的都是object或IList或类似的,并且列表在运行时可以是任何类型)

If you know it is a List<T>, then:

如果您知道它是一个列表 ,则:

Type type = abc.GetType().GetGenericArguments()[0];

Another option is to look at the indexer:

另一个选择是查看索引器:

Type type = abc.GetType().GetProperty("Item").PropertyType;

Using new TypeInfo:

使用新的TypeInfo:

using System.Reflection;
// ...
var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];

#3


41  

With the following extension method you can get away without reflection:

使用以下扩展方法,你可以不加思索地离开:

public static Type GetListType<T>(this List<T> _)
{
    return typeof(T);
}

Or more general:

或更一般的:

public static Type GetEnumeratedType<T>(this IEnumerable<T> _)
{
    return typeof(T);
}

Usage:

用法:

List<string>        list    = new List<string> { "a", "b", "c" };
IEnumerable<string> strings = list;
IEnumerable<object> objects = list;

Type listType    = list.GetListType();           // string
Type stringsType = strings.GetEnumeratedType();  // string
Type objectsType = objects.GetEnumeratedType();  // BEWARE: object

#4


26  

Try

试一试

list.GetType().GetGenericArguments()

#5


12  

That's work for me. Where myList is some unknowed kind of list.

这对我的工作。其中myList是一些unknowed类型的列表。

IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;

#6


9  

Consider this: I use it to export 20 typed list by same way:

考虑一下:我用它来导出20个类型化列表:

private void Generate<T>()
{
    T item = (T)Activator.CreateInstance(typeof(T));

    ((T)item as DemomigrItemList).Initialize();

    Type type = ((T)item as DemomigrItemList).AsEnumerable().FirstOrDefault().GetType();
    if (type == null) return;
    if (type != typeof(account)) //account is listitem in List<account>
    {
        ((T)item as DemomigrItemList).CreateCSV(type);
    }
}

#7


5  

The GetGenericArgument() method has to be set on the Base Type of your instance (whose class is a generic class myClass<T>). Otherwise, it returns a type[0]

GetGenericArgument()方法必须设置在实例的基类型上(其类是通用类myClass )。否则,它返回一个类型[0]

Example:

例子:

Myclass<T> instance = new Myclass<T>();
Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();

#8


5  

If you dont need the whole Type variable and just want to check the type you can easily create a temp variable and use is operator.

如果您不需要整个类型变量,只想检查类型,您可以轻松创建一个临时变量并使用is操作符。

T checkType = default(T);

if (checkType is MyClass)
{}

#9


4  

public string ListType<T>(T value){
    var valueType = value.GetType().GenericTypeArguments[0].FullName;
    return value;
}

You can use this one for rerun type of generic list.

您可以使用这个来重新运行泛型列表的类型。

#10


3  

You can get the type of "T" from any collection type that implements IEnumerable<T> with the following:

您可以从任何实现IEnumerable 的集合类型中获得“T”的类型,如下所示:

public static Type GetCollectionItemType(Type collectionType)
{
    var types = collectionType.GetInterfaces()
        .Where(x => x.IsGenericType 
            && x.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        .ToArray();
    // Only support collections that implement IEnumerable<T> once.
    return types.Length == 1 ? types[0].GetGenericArguments()[0] : null;
}

Note that it doesn't support collection types that implement IEnumerable<T> twice, e.g.

注意,它不支持实现两次IEnumerable 的集合类型,例如。

public class WierdCustomType : IEnumerable<int>, IEnumerable<string> { ... }

I suppose you could return an array of types if you needed to support this...

如果您需要支持这个,我想您可以返回一个类型数组……

Also, you might also want to cache the result per collection type if you're doing this a lot (e.g. in a loop).

此外,如果您经常这样做(例如在循环中),您可能还想缓存每个集合类型的结果。

#11


2  

I use this extension method to accomplish something similar:

我使用这个扩展方法来完成类似的事情:

public static string GetFriendlyTypeName(this Type t)
{
    var typeName = t.Name.StripStartingWith("`");
    var genericArgs = t.GetGenericArguments();
    if (genericArgs.Length > 0)
    {
        typeName += "<";
        foreach (var genericArg in genericArgs)
        {
            typeName += genericArg.GetFriendlyTypeName() + ", ";
        }
        typeName = typeName.TrimEnd(',', ' ') + ">";
    }
    return typeName;
}

You use it like this:

你可以这样使用:

[TestMethod]
public void GetFriendlyTypeName_ShouldHandleReallyComplexTypes()
{
    typeof(Dictionary<string, Dictionary<string, object>>).GetFriendlyTypeName()
        .ShouldEqual("Dictionary<String, Dictionary<String, Object>>");
}

This isn't quite what you're looking for, but it's helpful in demonstrating the techniques involved.

这并不是您所要寻找的,但是它有助于演示所涉及的技术。

#12


1  

Using 3dGrabber's solution:

使用3 dgrabber的解决办法:

public static T GetEnumeratedType<T>(this IEnumerable<T> _)
{
    return default(T);
}

//and now 

var list = new Dictionary<string, int>();
var stronglyTypedVar = list.GetEnumeratedType();

#13


0  

public bool IsCollection<T>(T value){
  var valueType = value.GetType();
  return valueType.IsArray() || typeof(IEnumerable<object>).IsAssignableFrom(valueType) || typeof(IEnumerable<T>).IsAssignableFrom(valuetype);
}

#14


0  

If you want to know a property's underlying type, try this:

如果您想知道属性的底层类型,请尝试以下方法:

propInfo.PropertyType.UnderlyingSystemType.GenericTypeArguments[0]

#15


0  

This is how i did it

我就是这么做的

internal static Type GetElementType(this Type type)
{
        //use type.GenericTypeArguments if exist 
        if (type.GenericTypeArguments.Any())
         return type.GenericTypeArguments.First();

         return type.GetRuntimeProperty("Item").PropertyType);
}

Then call it like this

然后这样称呼它

var item = Activator.CreateInstance(iListType.GetElementType());

OR

var item = Activator.CreateInstance(Bar.GetType().GetElementType());

#16


-9  

Type:

类型:

type = list.AsEnumerable().SingleOrDefault().GetType();

#1


546  

If I understand correctly, your list has the same type parameter as the container class itself. If this is the case, then:

如果我理解正确,您的列表具有与容器类本身相同的类型参数。如果是这样,则:

Type typeParameterType = typeof(T);

If you are in the lucky situation of having object as a type parameter, see Marc's answer.

如果您幸运地将对象作为类型参数,请参阅Marc的答案。

#2


452  

(note: I'm assuming that all you know is object or IList or similar, and that the list could be any type at runtime)

(注意:我假设您所知道的都是object或IList或类似的,并且列表在运行时可以是任何类型)

If you know it is a List<T>, then:

如果您知道它是一个列表 ,则:

Type type = abc.GetType().GetGenericArguments()[0];

Another option is to look at the indexer:

另一个选择是查看索引器:

Type type = abc.GetType().GetProperty("Item").PropertyType;

Using new TypeInfo:

使用新的TypeInfo:

using System.Reflection;
// ...
var type = abc.GetType().GetTypeInfo().GenericTypeArguments[0];

#3


41  

With the following extension method you can get away without reflection:

使用以下扩展方法,你可以不加思索地离开:

public static Type GetListType<T>(this List<T> _)
{
    return typeof(T);
}

Or more general:

或更一般的:

public static Type GetEnumeratedType<T>(this IEnumerable<T> _)
{
    return typeof(T);
}

Usage:

用法:

List<string>        list    = new List<string> { "a", "b", "c" };
IEnumerable<string> strings = list;
IEnumerable<object> objects = list;

Type listType    = list.GetListType();           // string
Type stringsType = strings.GetEnumeratedType();  // string
Type objectsType = objects.GetEnumeratedType();  // BEWARE: object

#4


26  

Try

试一试

list.GetType().GetGenericArguments()

#5


12  

That's work for me. Where myList is some unknowed kind of list.

这对我的工作。其中myList是一些unknowed类型的列表。

IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;

#6


9  

Consider this: I use it to export 20 typed list by same way:

考虑一下:我用它来导出20个类型化列表:

private void Generate<T>()
{
    T item = (T)Activator.CreateInstance(typeof(T));

    ((T)item as DemomigrItemList).Initialize();

    Type type = ((T)item as DemomigrItemList).AsEnumerable().FirstOrDefault().GetType();
    if (type == null) return;
    if (type != typeof(account)) //account is listitem in List<account>
    {
        ((T)item as DemomigrItemList).CreateCSV(type);
    }
}

#7


5  

The GetGenericArgument() method has to be set on the Base Type of your instance (whose class is a generic class myClass<T>). Otherwise, it returns a type[0]

GetGenericArgument()方法必须设置在实例的基类型上(其类是通用类myClass )。否则,它返回一个类型[0]

Example:

例子:

Myclass<T> instance = new Myclass<T>();
Type[] listTypes = typeof(instance).BaseType.GetGenericArguments();

#8


5  

If you dont need the whole Type variable and just want to check the type you can easily create a temp variable and use is operator.

如果您不需要整个类型变量,只想检查类型,您可以轻松创建一个临时变量并使用is操作符。

T checkType = default(T);

if (checkType is MyClass)
{}

#9


4  

public string ListType<T>(T value){
    var valueType = value.GetType().GenericTypeArguments[0].FullName;
    return value;
}

You can use this one for rerun type of generic list.

您可以使用这个来重新运行泛型列表的类型。

#10


3  

You can get the type of "T" from any collection type that implements IEnumerable<T> with the following:

您可以从任何实现IEnumerable 的集合类型中获得“T”的类型,如下所示:

public static Type GetCollectionItemType(Type collectionType)
{
    var types = collectionType.GetInterfaces()
        .Where(x => x.IsGenericType 
            && x.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        .ToArray();
    // Only support collections that implement IEnumerable<T> once.
    return types.Length == 1 ? types[0].GetGenericArguments()[0] : null;
}

Note that it doesn't support collection types that implement IEnumerable<T> twice, e.g.

注意,它不支持实现两次IEnumerable 的集合类型,例如。

public class WierdCustomType : IEnumerable<int>, IEnumerable<string> { ... }

I suppose you could return an array of types if you needed to support this...

如果您需要支持这个,我想您可以返回一个类型数组……

Also, you might also want to cache the result per collection type if you're doing this a lot (e.g. in a loop).

此外,如果您经常这样做(例如在循环中),您可能还想缓存每个集合类型的结果。

#11


2  

I use this extension method to accomplish something similar:

我使用这个扩展方法来完成类似的事情:

public static string GetFriendlyTypeName(this Type t)
{
    var typeName = t.Name.StripStartingWith("`");
    var genericArgs = t.GetGenericArguments();
    if (genericArgs.Length > 0)
    {
        typeName += "<";
        foreach (var genericArg in genericArgs)
        {
            typeName += genericArg.GetFriendlyTypeName() + ", ";
        }
        typeName = typeName.TrimEnd(',', ' ') + ">";
    }
    return typeName;
}

You use it like this:

你可以这样使用:

[TestMethod]
public void GetFriendlyTypeName_ShouldHandleReallyComplexTypes()
{
    typeof(Dictionary<string, Dictionary<string, object>>).GetFriendlyTypeName()
        .ShouldEqual("Dictionary<String, Dictionary<String, Object>>");
}

This isn't quite what you're looking for, but it's helpful in demonstrating the techniques involved.

这并不是您所要寻找的,但是它有助于演示所涉及的技术。

#12


1  

Using 3dGrabber's solution:

使用3 dgrabber的解决办法:

public static T GetEnumeratedType<T>(this IEnumerable<T> _)
{
    return default(T);
}

//and now 

var list = new Dictionary<string, int>();
var stronglyTypedVar = list.GetEnumeratedType();

#13


0  

public bool IsCollection<T>(T value){
  var valueType = value.GetType();
  return valueType.IsArray() || typeof(IEnumerable<object>).IsAssignableFrom(valueType) || typeof(IEnumerable<T>).IsAssignableFrom(valuetype);
}

#14


0  

If you want to know a property's underlying type, try this:

如果您想知道属性的底层类型,请尝试以下方法:

propInfo.PropertyType.UnderlyingSystemType.GenericTypeArguments[0]

#15


0  

This is how i did it

我就是这么做的

internal static Type GetElementType(this Type type)
{
        //use type.GenericTypeArguments if exist 
        if (type.GenericTypeArguments.Any())
         return type.GenericTypeArguments.First();

         return type.GetRuntimeProperty("Item").PropertyType);
}

Then call it like this

然后这样称呼它

var item = Activator.CreateInstance(iListType.GetElementType());

OR

var item = Activator.CreateInstance(Bar.GetType().GetElementType());

#16


-9  

Type:

类型:

type = list.AsEnumerable().SingleOrDefault().GetType();