如何从generics类或方法的成员中获取T的types?

假设我在类或方法中有一个通用成员,所以:

public class Foo<T> { public List<T> Bar { get; set; } public void Baz() { // get type of T } } 

当我实例化类, T成为MyTypeObject1 ,所以类有一个通用的列表属性: List<MyTypeObject1> 。 这同样适用于非generics类中的generics方法:

 public class Foo { public void Bar<T>() { var baz = new List<T>(); // get type of T } } 

我想知道,我的类包含什么types的对象。 那么名为Bar或者局部variablesbaz的list属性包含了什么types的T

我不能做Bar[0].GetType() ,因为列表可能包含零个元素。 我该怎么做?

如果我理解正确,你的列表与容器类本身具有相同的types参数。 如果是这种情况,那么:

 Type typeParameterType = typeof(T); 

如果您处于以object作为types参数的幸运情境,请参阅Marc的回答 。

(注意:我假设你所知道的只是objectIList或类似的东西,而且这个列表在运行时可以是任何types的)

如果你知道它是一个List<T> ,那么:

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

另一个select是看索引器:

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

使用新的TypeInfo:

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

使用下面的扩展方法,你可以不经过反思:

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

或者更一般的:

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

用法:

 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 

尝试

 list.GetType().GetGenericArguments() 

这对我有用。 myList是一些不知名的列表。

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

考虑到这一点:我用它来导出20types列表相同的方式:

 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); } } 

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

例:

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

如果你不需要整个typesvariables,只想检查types,你可以很容易地创build一个临时variables,并使用运算符。

 T checkType = default(T); if (checkType is MyClass) {} 

您可以从任何实现IEnumerable <T>的集合types获取“T”types,其中包含以下内容:

 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; } 

请注意,它不支持实现IEnumerable <T>两次的集合types,例如

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

我想你可以返回一个数组types,如果你需要支持这个…

另外,如果你正在做很多事情(比如在一个循环中),你也可能想要caching每个集合types的结果。

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

 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; } 

你这样使用它:

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

这不是你要找的东西,但是它有助于展示所涉及的技术。

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

您可以使用这个重新运行types的通用列表。

使用3dGrabber的解决scheme:

 public static T GetEnumeratedType<T>(this IEnumerable<T> _) { return default(T); } //and now var list = new Dictionary<string, int>(); var stronglyTypedVar = list.GetEnumeratedType(); 
 public bool IsCollection<T>(T value){ var valueType = value.GetType(); return valueType.IsArray() || typeof(IEnumerable<object>).IsAssignableFrom(valueType) || typeof(IEnumerable<T>).IsAssignableFrom(valuetype); } 

如果你想知道一个属性的基础types,试试这个:

 propInfo.PropertyType.UnderlyingSystemType.GenericTypeArguments[0] 

这是我做到的

 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); } 

然后像这样调用它

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

要么

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

types:

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