• 由IEnumerable和IEnumerator的延伸


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

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

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

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

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

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

    1 public static class DataTableConvertToList
    2     {
    3   //使用静态方法扩展datatable
    4         public static IEnumerable<T> FillObjects<T>(this DataTable dataTable) where T : class
    5         {
    6             return new DataTableEnumerable<T>() { Data = dataTable };
    7       }
    8      }
     1 public class DataTableEnumerable<T> : IEnumerable<T>
     2     {
     3         public DataTable Data;
     4 
     5         public IEnumerator<T> GetEnumerator()
     6         {
     7             return new DataTableEnumerator<T>(Data);
     8         }
     9 
    10         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    11         {
    12             return new DataTableEnumerator<T>(Data);
    13         }
    14 
    15       }
    View Code
     1 public class DataTableEnumerator<T> : IEnumerator<T>
     2     {
     3         private DataTable data;
     4         private int index = -1;
     5 
     6         public DataTableEnumerator(DataTable data)
     7         {
     8             if (data == null)
     9             {
    10                 data = new DataTable();
    11             }
    12             this.data = data;
    13         }
    14 
    15         public T Current
    16         {
    17             get { return convert(); }
    18         }
    19 
    20         public void Dispose() { }
    21 
    22         object System.Collections.IEnumerator.Current
    23         {
    24             get { return convert(); }
    25         }
    26 
    27         public bool MoveNext()
    28         {
    29             index++;
    30             return index < data.Rows.Count;
    31         }
    32 
    33         public void Reset()
    34         {
    35             index = -1;
    36         }
    37 
    38         private T convert()
    39         {
    40             var row = data.Rows[index];
    41 
    42             var tType = typeof(T);
    43 
    44             var properties = tType.GetProperties();
    45 
    46   //反射动态调用这个类
    47             var obj = tType.GetConstructor(new Type[] { }).Invoke(null);
    48 
    49             foreach (DataColumn col in data.Columns)
    50             {
    51                 var val = row[col];
    52                 if (val.GetType() == typeof(DBNull))
    53                 {
    54                     continue;
    55                 }
    56                 var prop = properties.SingleOrDefault(m => m.Name.ToUpper() == col.ColumnName.ToUpper());
    57                 if (prop == null)
    58                 {
    59                     continue;
    60                 }
    61                 if (prop.PropertyType.IsGenericType && prop.PropertyType.Name == typeof(Nullable<>).Name)
    62                 {
    63                     prop.SetValue(obj,Convert.ChangeType(val, prop.PropertyType.GetGenericArguments()[0]), null);
    64                 }
    65                 else
    66                 {
    67     
    68                     prop.SetValue(obj, Convert.ChangeType(val, prop.PropertyType), null);
    69                 }
    70             }
    71 
    72             return (T)obj;
    73         }
    74       }
    75   
    View Code

      最后我们来看下效果:

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

  • 相关阅读:
    37 什么时候使用内部临时表
    2 Hadoop集群安装部署准备
    36 为什么临时表可以重名
    maven内置属性
    ProGuard 最全混淆规则说明
    stylus的用法
    vscode 插件 配置
    关于overflow:hidden
    vue-devtools/安装vue-devtools
    对Java中使用两个大括号进行初始化的理解
  • 原文地址:https://www.cnblogs.com/qiuyan/p/3157891.html
Copyright © 2020-2023  润新知