相信大家在学习c#的时候,经常会看到IEnumerable、IEnumerator这样的接口或返回类型,在写代码时经常会对数组或List集合进行遍历。那IEnumerable和IEnumerator是干什么的呢?有什么区别?数组和List集合为什么可以遍历而其他某些类型或对象不能遍历?它们之间有什么联系呢?

  针对这么多疑问,我本来是想来写一篇文章来记录下的,但我在网上又发现了一篇写的很好的文章,对它们之间的关系讲的很详细,我觉得就算我写的话,不见得写的比这篇文章好 :-)。以下是文章链接 http://blog.csdn.net/byondocean/article/details/6871881 推荐看,不然会影响对后面代码的理解,(老鸟忽略)当然了,这些都不是本文的重点,就如文章的标题,我想写的是 ”由IEnumerable和IEnumerator的延伸“,。。。好吧,我们正式进入主题。

  比如我们在开发某个功能时,页面查询的数据量比较大,并且关联的表也很多, 这个时候写sql语句无疑是首选,但我们为了便于操作,还要把DataTable遍历转换成List,当然你会说,一般ORM框架不是支持原生的SQL语句吗?比如EF的SqlQuery,它直接就返回了可枚举的对象了。是的,但OMR框架再怎么封装,最终也是通过ADO.NET方式访问数据库的。

我们通过查询得到了一个DataTable数据集合,这个时候我们让它返回List,我们希望的调用方式如下:

 var data = oh.excuteQuery(strSql).FillObjects<Person>().ToList();

  传入一个Person 返回 List<Person >非常简洁的调用,像Linq to objects 般流畅,接下来我们就来实现它吧。

 public static class DataTableConvertToList
{
  //使用静态方法扩展datatable
public static IEnumerable<T> FillObjects<T>(this DataTable dataTable) where T : class
{
return new DataTableEnumerable<T>() { Data = dataTable };
}
}
 public class DataTableEnumerable<T> : IEnumerable<T>
{
public DataTable Data; public IEnumerator<T> GetEnumerator()
{
return new DataTableEnumerator<T>(Data);
} System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new DataTableEnumerator<T>(Data);
}    }
 public class DataTableEnumerator<T> : IEnumerator<T>
{
private DataTable data;
private int index = -; public DataTableEnumerator(DataTable data)
{
if (data == null)
{
data = new DataTable();
}
this.data = data;
} public T Current
{
get { return convert(); }
} public void Dispose() { } object System.Collections.IEnumerator.Current
{
get { return convert(); }
} public bool MoveNext()
{
index++;
return index < data.Rows.Count;
} public void Reset()
{
index = -;
} private T convert()
{
var row = data.Rows[index]; var tType = typeof(T); var properties = tType.GetProperties();   //反射动态调用这个类
var obj = tType.GetConstructor(new Type[] { }).Invoke(null); foreach (DataColumn col in data.Columns)
{
var val = row[col];
if (val.GetType() == typeof(DBNull))
{
continue;
}
var prop = properties.SingleOrDefault(m => m.Name.ToUpper() == col.ColumnName.ToUpper());
if (prop == null)
{
continue;
}
if (prop.PropertyType.IsGenericType && prop.PropertyType.Name == typeof(Nullable<>).Name)
{
prop.SetValue(obj,Convert.ChangeType(val, prop.PropertyType.GetGenericArguments()[]), null);
}
else
{
  
prop.SetValue(obj, Convert.ChangeType(val, prop.PropertyType), null);
}
} return (T)obj;
}
   }
  

  最后我们来看下效果:

  上面总的框架是通过继承IEnumerable和IEnumerator 接口来实现迭代的,最后的绑定是通过反射实现的。

由IEnumerable和IEnumerator的延伸的更多相关文章

  1. C# ~ 从 IEnumerable / IEnumerator 到 IEnumerable<T> / IEnumerator<T> 到 yield

    IEnumerable / IEnumerator 首先,IEnumerable / IEnumerator 接口定义如下: public interface IEnumerable /// 可枚举接 ...

  2. 细说 C# 中的 IEnumerable和IEnumerator接口

    我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq to Object中要返回IEnumerable? 接下来,先开始我们的正 ...

  3. 迭代器学习之一:使用IEnumerable和IEnumerator接口

    写博客是检验我学习的成果之一以及自我总结的一种方式,以后会经常利用这种方式进行技术交流和自我总结,其中认识不深难免会有错误,但是一直懂得不懂就问,不懂就学的道理! 1.首先看一个简单的列子 , , , ...

  4. IEnumerable和IEnumerator

    概述 IEnumerable和IEnumerator接口存在的意义:用来实现迭代的功能! public interface IEnumerable { IEnumerator GetEnumerato ...

  5. 关于迭代器中IEnumerable与IEnumerator的区别

    首先是IEnumerable与IEnumerator的定义: 1.IEnumerable接口允许使用foreach循环,包含GetEnumerator()方法,可以迭代集合中的项. 2.IEnumer ...

  6. IEnumerable和IEnumerator 详解 (转)

    原文链接:http://blog.csdn.net/byondocean/article/details/6871881 参考链接:http://www.cnblogs.com/hsapphire/a ...

  7. C#基础知识系列九(对IEnumerable和IEnumerator接口的糊涂认识)

    前言 IEnumerable.IEnumerator到现在为止对这两个接口还是不太理解,不理解但是自己总是想着试着要搞明白,毕竟自己用的少,所以在此先记录一下.以备自己日后可以来翻查,同时也希望园子里 ...

  8. [转]那些年我还不懂:IList,ICollection,IEnumerable,IEnumerator,IQueryable

    1.首先看一个简单的例子 int[] myArray = { 1, 32, 43, 343 }; IEnumerator myie = myArray.GetEnumerator(); myie.Re ...

  9. 转载IEnumerable与IEnumerator区别

    public interface IEnumerable {     IEnumerator GetEnumerator(); }   public interface IEnumerator {   ...

随机推荐

  1. HTML5 Canvas简简单单实现手机九宫格手势密码解锁

    原文:HTML5 Canvas简简单单实现手机九宫格手势密码解锁 早上花了一个半小时写了一个基于HTML Canvas的手势解锁,主要是为了好玩,可能以后会用到. 思路:根据配置计算出九个点的位置,存 ...

  2. 利用svn自动同步更新到网站服务器 -- 网摘

    首先在服务器上安装VisualSVN Server ,根据提示选好安装的路径,一路确定.安装好后运行VisualSVN Server ,在Repositories上点击右键,选择create New ...

  3. BZOJ 1208 HNOI2004 宠物收容所 平衡树/set

    标题效果:有一个宠物收容所.目前还没有被采纳的宠物或谁想要领养宠物,每个宠物有个性值,大家谁想要领养宠物具有理想人格值.每一刻,宠物收容所只是为了有谁想要领养宠物或宠物的人. 当领走宠物,将有一定程度 ...

  4. sax(用于处理XML事件驱动的推模型)解析例子

    SAX解析 Java程序如下: import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; impor ...

  5. CSS学习笔记:Media Queries

    CSS3提供了Media Queries(媒体查询)的概念,可以利用它查询以下数据: 1.浏览器窗口的宽和高: 2.设备的宽和高: 3.设备的手持方向,横向/竖向: 4.分辨率. @media规则的语 ...

  6. UC编程:输入输出重定向(系统调用)

    在Unix下,系统重定向是使用dup和dup2函数完成的 在学习使用这两个函数之前,必须要搞懂一个概念就是文件描述符 摘自:<文件描述符和文件指针的区别> 文件描述符就是open文件时产生 ...

  7. 图文详解ReSharper 8.1功能变化

    ReSharper 8.1版本已经发布有段时间了,被广大开发者购买和试用,今天小编就ReSharper 8.1功能变化就行详细的解说. 支持TypeScript 突出了重构(重命名,引入变量).导航. ...

  8. [译]Java 设计模式之工厂

    (文章翻译自Java Design Pattern: Factory) 1.Java工厂模式的来历 工厂设计模式用于创建基于不同参数的对象.下面的例子就是在一个工厂里创建一个人.如果我们向工厂要一个b ...

  9. SQL Server 复制 - 发布订阅(SQL Server 数据同步)

    原文:SQL Server 复制 - 发布订阅(SQL Server 数据同步) SQL Server的同步是通过SQL Server自带的复制工具来实现的,分发布和订阅2大步. A,复制-发布 发布 ...

  10. Smarty include

    注:由于水平有限,欢迎指正.转载请务必注明出处. 1     include Attribute Name Type Required Default 描述 file string Yes n/a T ...