CSharp - 如何获取T 的类型和泛型List<T>

  显示原文与译文双语对照的内容

假设我有一个 List<T> abc = new List <T> ; 在类 public class MyClass<T>//... 中。

以后,初始化类时,T 变为 MyTypeObject1 。 所以我有一个通用的List,List <MyTypeObject1>

我想知道,类的List的类型是什么,比如 调用的List 包含了对象的类型?

无法执行 abc[0].GetType();,因为 List 可能包含零元素。 我该怎么做?

时间:

如果我正确理解,你的List 具有与容器类本身相同的类型参数。 如果是这样,那么:


Type typeParameterType = typeof(T);

如果你有幸将对象作为类型参数,请参阅marc的回答。

( 注意:我假设你所知道的是 object 或者 IList 或者类似的,并且 List 可以是运行时的任何类型)

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


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

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


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

使用新类型类型:


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

考虑这样:我使用同样的方式导出 20类型的List:


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() 方法必须在实例( 它的类是泛型类 myClass<T> )的基类型上设置。 否则,它返回一个类型 [0 ]

例如:


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

和这些following,你可以获取"T"的类型由它的集合类型,它实现重复元素除外 <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;
}

请注意,它不支持实现 IEnumerable <> 两次的集合类型,e.g.


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

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

此外,如果你正在进行大量的操作,也可能需要缓存每个集合类型的结果( 例如。 在循环中) 。

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


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

...