目录

介绍

概念化这个混乱

编码此混乱


  • 下载实用程序-5.7 KB

介绍

通过这个技巧,我将努力向读者展示如何使用反射来查询一个集合类的元素类型。当涉及到未实现IEnumerable<T>的类型化集合时,一开始看起来相对简单的事情很快就变得复杂起来了。在.NET 2.0之前创建的类型化集合就是这种情况。这些集合非常普遍。例如,许多Windows窗体以及CodeDOM都是这样的集合的类型。这些集合更需要获取元素类型。

概念化这个混乱

有时我们可能需要通过反射来获取集合的元素类型。我通常在编写代码生成器时遇到此问题。这对于.NET post 1.1而言是微不足道的,但是在此之前,由于无法创建可以处理该类型的通用接口,因此没有用于类型化集合的标准接口。

为了获得通用的集合类型,在这种情况下,我们要做的就是查询IEnumerable<T>接口,然后返回任何T内容。简单易用,它也适用于词典。

不幸的是,为了获得非泛型的集合元素类型,我们必须使用一些启发式方法。

我们要做的第一件事是查询IDictionary接口。如果找到它,我们将返回DictionaryEntry。

如果没有结果,接下来我们进行查询IList,如果找到它,我们将寻找一个采用单个整数参数并返回除object以外的其他类型的公共索引器属性。

最后,如果找不到,我们查找ICollection,并查找具有单个参数的Add()方法,该参数不是object类型的。我发现这是确定集合的元素类型的最可靠方法。

最后,如果那行不通,我们寻找IEnumerable并找到它,然后返回object类型。否则,我们返回null表明它不是集合类型。我们可以在枚举器的IEnumerator接口上查询Current属性,但是,没有可靠的方法可以在不调用实例上的GetEnumerator()的情况下获得枚举数的类型。在实践中,我认为我没有看到太多不是泛型的类型化枚举器实现。

编码此混乱

像我通常所做的那样,我将几乎完整地发布代码,然后从上至下进行处理:

static partial class ReflectionUtility
{/// <summary>/// Indicates whether or not the specified type is a list./// </summary>/// <param name="type">The type to query</param>/// <returns>True if the type is a list, otherwise false</returns>public static bool IsList(Type type){if (null == type)throw new ArgumentNullException("type");if (typeof(System.Collections.IList).IsAssignableFrom(type))return true;foreach (var it in type.GetInterfaces())if (it.IsGenericType && typeof(IList<>) == it.GetGenericTypeDefinition())return true;return false;}/// <summary>/// Retrieves the collection element type from this type/// </summary>/// <param name="type">The type to query</param>/// <returns>The element type of the collection or null if the type was not a collection/// </returns>public static Type GetCollectionElementType(Type type){if (null == type)throw new ArgumentNullException("type");// first try the generic way// this is easy, just query the IEnumerable<T> interface for its generic parametervar etype = typeof(IEnumerable<>);foreach (var bt in type.GetInterfaces())if (bt.IsGenericType && bt.GetGenericTypeDefinition() == etype)return bt.GetGenericArguments()[0];// now try the non-generic way// if it's a dictionary we always return DictionaryEntryif (typeof(System.Collections.IDictionary).IsAssignableFrom(type))return typeof(System.Collections.DictionaryEntry);// if it's a list we look for an Item property with an int index parameter// where the property type is anything but objectif (typeof(System.Collections.IList).IsAssignableFrom(type)){foreach (var prop in type.GetProperties()){if ("Item" == prop.Name && typeof(object)!=prop.PropertyType){var ipa = prop.GetIndexParameters();if (1 == ipa.Length && typeof(int) == ipa[0].ParameterType){return prop.PropertyType;}}}}// if it's a collection, we look for an Add() method whose parameter is // anything but objectif(typeof(System.Collections.ICollection).IsAssignableFrom(type)){foreach(var meth in type.GetMethods()){if("Add"==meth.Name){var pa = meth.GetParameters();if (1 == pa.Length && typeof(object) != pa[0].ParameterType)return pa[0].ParameterType;}}}if (typeof(System.Collections.IEnumerable).IsAssignableFrom(type))return typeof(object);return null;}
}

首先,我们有一个上面没有提到的IsList()方法。这是一种实用程序方法,当我对集合进行反射时,我发现自己需要很多,因此在此提供了它。它所做的只是确定传入的类型是否为列表。

现在,在GetCollectionElementType()中,我们将按照本文概念部分中概述的步骤进行操作。首先,我们尝试确定元素类型的泛型方法,如果不成功,我们将转到非泛型测试部分,在该部分中,我们首先查找this[]索引器属性,如果失败,则使用该Add()方法。

使用代码非常简单:

Console.WriteLine(ReflectionUtility.GetCollectionElementType(typeof(List<string>)));
Console.WriteLine(ReflectionUtility.GetCollectionElementType(typeof(List<int>)));
Console.WriteLine(ReflectionUtility.GetCollectionElementType(typeof(CodeNamespaceCollection)));
Console.WriteLine(ReflectionUtility.GetCollectionElementType(typeof(CodeStatementCollection)));

这应该足以使您继续使用此代码。请享用!

如何在C#中使用反射获取集合元素类型相关推荐

  1. 如何在XCode中更改iPhone或iPad模拟器类型

    如何在XCode中更改iPhone或iPad模拟器类型 参考方法一(永久,一旦设置后,每次运行指定的模拟器):(1)选择顶层菜单Project 中的 Set Active Executable(2)根 ...

  2. Python精讲:在Python中添加和删除集合元素详解

    欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python中添加和删除集合元素详解>.本知识点主要讲的是添加和删除元素,包括:在Python中向集合里面添加元素可以使用 ...

  3. 来看看如何在 C# 中使用反射

    C# 中的 反射 常用于在程序的运行时获取 类型 的元数据,可获取的信息包括已加载到进程中的 程序集 和 类型 信息,它和 C++ 中的 RTTI(Runtime Type Information) ...

  4. 如何在 C# 中使用 反射

    C# 中的 反射 常用于在程序的运行时获取 类型 的元数据,可获取的信息包括已加载到进程中的 程序集 和 类型 信息,它和 C++ 中的 RTTI(Runtime Type Information) ...

  5. SpringBoot中访问Thymeleaf提示:元素类型 meta 必须由匹配的结束标记终止。

    场景 新建SpringBoot项目后整合Thymelaf后访问页面提示: 元素类型 "meta" 必须由匹配的结束标记 "</meta>" 终止. ...

  6. Redis 笔记(06)— set 类型(向集合添加元素、获取集合元素个数、判断集合中是否包含某个元素、删除给定元素、返回集合中所有元素、计算集合的交集、并集、差集)

    Redis 的 set 集合内部的键值对是无序的唯一的.它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL .当集合中最后一个元素移除之后,数据结构自动删除,内存被回收. ...

  7. java 反射父类私有属性值_如何在Java中通过反射访问父类的父类的私有字段? - java...

    在一个API中,我使用的是一个抽象类(A类),该类具有一个私有字段(A.privateField). B类在API中扩展了A类. 我需要扩展B类的实现,即C类,但是我需要A类的privateField ...

  8. android wifi定位服务,如何在Android中使用Wifi获取位置?

    我希望通过Wifi获取位置并在谷歌地图中工作,这对我不起作用,但Gps没问题,也没问题. 我的代码: locationManager = (LocationManager) getSystemServ ...

  9. java获取列族的列_在cassandra-cli中如何获取表中的所有列名以及如何在java中使用hector获取它?...

    我正在尝试获取列名,但无法获得仅列名称. 在cli我执行命令描述表节点,它返回结果: CREATE TABLE nodes ( key text PRIMARY KEY, id text, score ...

最新文章

  1. 关于Blocking IO, Non-Blocking IO 和 Asynchronous I/O的理解
  2. python2中如何得到一级域名
  3. kafkatool 配置_kafka tools的使用
  4. oracle 11.2 安装asm,oracle11r2安装asm+rac配置步骤.doc
  5. 第三次学JAVA再学不好就吃翔(part23)--private和this
  6. 老刘在微软Ignite China大会上聊低代码
  7. 不同DPI下窗体的自适应的有关注意点(转)
  8. python多元函数求极小值_使用遗传算法求二元函数的最小值
  9. shell中的正则表达式
  10. linux设备驱动模型一字符设备open系统调用流程
  11. 重复组合公式及其证明方法
  12. 物联网开发 7 旗点云物联网云平台
  13. 原来变压器可以用来调节阻抗匹配!
  14. 中国“千禧一代”是一群什么样的消费者?
  15. 还不了解Oauth2协议?这篇文章从入门到入土让你了解Oauth2以及Spring Security OAuth2 的使用
  16. kali 2019安装8812bu无线网卡驱动
  17. [Unity] Catan Universe: Unity 的移动设备优化
  18. 如何在typescript中importfs模块
  19. 2010年财富杂志全球500强榜公布 沃尔玛居榜首
  20. java.lang.NoClassDefFoundError: Could not initialize class错误原因

热门文章

  1. android iot代码设计,一个简单好用的Android Tab 设计与实现
  2. linux gradle仓库位置,如何在Android Studio中使用Gradle发布项目至Jcenter仓库
  3. 新年春节海报素材精品,再也不怕老板催稿!
  4. UI版式设计模板,这样做才高级!
  5. react 遍历对象_React 和 Vue 之间的相爱相杀
  6. 打开程序并监听程序是否退出
  7. Redis 的 Sentinel哨兵介绍与源码分析(1):初始化部分
  8. LaTex在Linux下编写高质量的文档
  9. oracle的优化适用于mysql吗_性能优化之数据库优化,适用于Sqlite、Mysql、Oracle、Sql server,详细介绍了索引和事务及部分针对Sqlite的优化...
  10. Python String:一文彻底粉碎字符串