使用Linq返回DataTable类型结果集

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Reflection;

/// <summary>
///Linq To DataTable Type
/// </summary>

public static class DataSetLinqOperators
{
    
public static DataTable CopyToDataTable<T>(this IEnumerable<T> source)
    {
        
return new ObjectShredder<T>().Shred(source, nullnull);
    }

    
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<stringint> _ordinalMap;
    
private Type _type;

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

    
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;
    }
}

posted @ 2012-03-26 17:14  晴天有时下鱼  阅读(325)  评论(0)    收藏  举报