ToDataTable<T>思考

在现实的编程当中常会有要把一个IEnumerable接口的数据结构转换成一个DataTable的操作。

 

在C#3.0 Linq以前,我们可能多数会想到自己去写这样一个函数。今天看到国外一牛人些的一篇Blog实现了这样一个功能。

我把其中主要的封装代码复制下来以供学习之用:

ExpandedBlockStart.gif 代码
  public   static   class  DataSetLinqOperators
    {
        
public   static  DataTable CopyToDataTable < T > ( this  IEnumerable < T >  source)
        {
            
return   new  ObjectShredder < T > ().Shred(source,  null null );
        }

        
public   static  DataTable CopyToDataTable < T > ( this  IEnumerable < T >  source, 
                                                    DataTable table, LoadOption
?  options)
        {
            
return   new  ObjectShredder < T > ().Shred(source, table, options);
        }

    }

    
public   class  ObjectShredder < T >
    {
        
private  FieldInfo[] _fi;
        
private  PropertyInfo[] _pi;
        
private  Dictionary < string int >  _ordinalMap;
        
private  Type _type;

        
public  ObjectShredder()
        {
            _type 
=   typeof (T);
            _fi 
=  _type.GetFields();
            _pi 
=  _type.GetProperties();
            _ordinalMap 
=   new  Dictionary < string int > ();
        }

        
public  DataTable Shred(IEnumerable < T >  source, DataTable table, LoadOption ?  options)
        {
            
if  ( typeof (T).IsPrimitive)
            {
                
return  ShredPrimitive(source, table, options);   
            }
    

            
if  (table  ==   null )
            {
                table 
=   new  DataTable( typeof (T).Name);
            }

            
//  now see if need to extend datatable base on the type T + build ordinal map
            table  =  ExtendTable(table,  typeof (T));

            table.BeginLoadData();
            
using  (IEnumerator < T >  e  =  source.GetEnumerator())
            {
                
while  (e.MoveNext())
                {
                    
if  (options  !=   null )
                    {
                        table.LoadDataRow(ShredObject(table, e.Current), (LoadOption)options);
                    }
                    
else
                    {
                        table.LoadDataRow(ShredObject(table, e.Current), 
true );
                    }
                }
            }
            table.EndLoadData();
            
return  table;
        }

        
public  DataTable ShredPrimitive(IEnumerable < T >  source, DataTable table, LoadOption ?  options)
        {
            
if  (table  ==   null )
            {
                table 
=   new  DataTable( typeof (T).Name);
            }

            
if  ( ! table.Columns.Contains( " Value " ))
            {
                table.Columns.Add(
" Value " typeof (T));
            }

            table.BeginLoadData();
            
using  (IEnumerator < T >  e  =  source.GetEnumerator())
            {
                Object[] values 
=   new   object [table.Columns.Count];
                
while  (e.MoveNext())
                {
                    values[table.Columns[
" Value " ].Ordinal]  =  e.Current;

                    
if  (options  !=   null )
                    {
                        table.LoadDataRow(values, (LoadOption)options);
                    }
                    
else
                    {
                        table.LoadDataRow(values, 
true );
                    }
                }
            }
            table.EndLoadData();  
            
return  table; 
        }

        
public  DataTable ExtendTable(DataTable table, Type type)
        {
            
//  value is type derived from T, may need to extend table.
             foreach  (FieldInfo f  in  type.GetFields())
            {
                
if  ( ! _ordinalMap.ContainsKey(f.Name))
                {
                    DataColumn dc 
=  table.Columns.Contains(f.Name)  ?  table.Columns[f.Name]
                        : table.Columns.Add(f.Name, f.FieldType);
                    _ordinalMap.Add(f.Name, dc.Ordinal);               
                }
            }
            
foreach  (PropertyInfo p  in  type.GetProperties())
            {
                
if  ( ! _ordinalMap.ContainsKey(p.Name))
                {
                    DataColumn dc 
=  table.Columns.Contains(p.Name)  ?  table.Columns[p.Name]
                        : table.Columns.Add(p.Name, p.PropertyType);
                    _ordinalMap.Add(p.Name, dc.Ordinal);
                }
            }
            
return  table;
        }

        
public   object [] ShredObject(DataTable table, T instance)
        {

            FieldInfo[] fi 
=  _fi;
            PropertyInfo[] pi 
=  _pi;

            
if  (instance.GetType()  !=   typeof (T))
            {
                ExtendTable(table, instance.GetType());
                fi 
=  instance.GetType().GetFields();
                pi 
=  instance.GetType().GetProperties();
            }

            Object[] values 
=   new   object [table.Columns.Count];
            
foreach  (FieldInfo f  in  fi)
            {
                values[_ordinalMap[f.Name]] 
=  f.GetValue(instance);
            }

            
foreach  (PropertyInfo p  in  pi)
            {
                values[_ordinalMap[p.Name]] 
=  p.GetValue(instance,  null );
            }
            
return  values;
        }
    }


 简单的调用代码如下:

ExpandedBlockStart.gif 代码
  class  Sample
    {
        
static   void  Main( string [] args)
        {
            
//  create sequence 
            Item[] items  =   new  Item[] {  new  Book{Id  =   1 , Price  =   13.50 , Genre  =   " Comedy " , Author  =   " Jim Bob " }, 
                                        
new  Book{Id  =   2 , Price  =   8.50 , Genre  =   " Drama " , Author  =   " John Fox " },  
                                        
new  Movie{Id  =   1 , Price  =   22.99 , Genre  =   " Comedy " , Director  =   " Phil Funk " },
                                        
new  Movie{Id  =   1 , Price  =   13.40 , Genre  =   " Action " , Director  =   " Eddie Jones " }};

                        
            var query1 
=  from i  in  items
                         
where  i.Price  >   9.99
                         orderby i.Price
                         select i;

            
//  load into new DataTable
            DataTable table1  =  query1.CopyToDataTable();

            
//  load into existing DataTable - schemas match            
            DataTable table2  =   new  DataTable();
            table2.Columns.Add(
" Price " typeof ( int ));
            table2.Columns.Add(
" Genre " typeof ( string ));

            var query2 
=  from i  in  items
                         
where  i.Price  >   9.99
                         orderby i.Price
                         select 
new  {i.Price, i.Genre};

            query2.CopyToDataTable(table2, LoadOption.PreserveChanges);


            
//  load into existing DataTable - expand schema + autogenerate new Id.
            DataTable table3  =   new  DataTable();
            DataColumn dc 
=  table3.Columns.Add( " NewId " typeof ( int ));
            dc.AutoIncrement 
=   true ;
            table3.Columns.Add(
" ExtraColumn " typeof ( string ));

            var query3 
=  from i  in  items
                         
where  i.Price  >   9.99
                         orderby i.Price
                         select 
new  { i.Price, i.Genre };

            query3.CopyToDataTable(table3, LoadOption.PreserveChanges);

            
//  load sequence of scalars.

            var query4 
=  from i  in  items
                         
where  i.Price  >   9.99
                         orderby i.Price
                         select i.Price;

            var DataTable4 
=  query4.CopyToDataTable();
        }

        
public   class  Item
        {
            
public   int  Id {  get set ; }
            
public   double  Price {  get set ; }
            
public   string  Genre {  get set ; }   
        }

        
public   class  Book : Item
        {
            
public   string  Author {  get set ; }
        }

        
public   class  Movie : Item
        {
            
public   string  Director {  get set ; }
        }
        
    }


 

 



转载于:https://www.cnblogs.com/buhaiqing/archive/2010/01/21/1653673.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值