如何从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的回答 。
(注意:我假设你所知道的只是object
或IList
或类似的东西,而且这个列表在运行时可以是任何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();