How to get the type of T from a member of a generi

2018-12-31 05:55发布

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:

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?

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

标签: c# .net generics
16条回答
孤独寂梦人
2楼-- · 2018-12-31 06:39
public bool IsCollection<T>(T value){
  var valueType = value.GetType();
  return valueType.IsArray() || typeof(IEnumerable<object>).IsAssignableFrom(valueType) || typeof(IEnumerable<T>).IsAssignableFrom(valuetype);
}
查看更多
无与为乐者.
3楼-- · 2018-12-31 06:40
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.

查看更多
忆尘夕之涩
4楼-- · 2018-12-31 06:47

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

IEnumerable myEnum = myList as IEnumerable;
Type entryType = myEnum.AsQueryable().ElementType;
查看更多
君临天下
5楼-- · 2018-12-31 06:48

Using 3dGrabber's solution:

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

//and now 

var list = new Dictionary<string, int>();
var stronglyTypedVar = list.GetEnumeratedType();
查看更多
浪荡孟婆
6楼-- · 2018-12-31 06:48

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());
查看更多
宁负流年不负卿
7楼-- · 2018-12-31 06:49

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

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.

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

查看更多
登录 后发表回答