ToDataTable v2

DynamicObject & ExpandoObject should be accessed in different way.
 
 
        public static DataTable ToDataTable<T>( IEnumerable<T> input, string tableName)
        {
            var dt = new DataTable();
            dt.TableName = tableName;
 
            if (input == null || !input.Any()) return dt;
            if (typeof (T) == typeof(System. Object))
            {
                //"T is dynamic type"
                var first = Enumerable .First(input);
                if (first is IDictionary< string, object >)  //ExpandoObject also falls into this category         
                {
                    IDictionary<string , object> properties = ( IDictionary<string , object>)first;
 
                    foreach (var p in properties)
                    {
                        var type = p.Value.GetType();
                        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
                            type = type.GetGenericArguments()[0];
 
                        dt.Columns.Add(p.Key, type);
                    }
 
                    foreach (T r in input)
                    {
                        var values = new object[properties.Count];
                        int i = 0;
                        foreach (var p in properties)
                        {
                            values[i] = (r as IDictionary <string, object>)[p.Key];
                            i++;
                        }
 
                        dt.LoadDataRow(values, true);
                    }
                }
               
                else if (first is System.Dynamic. DynamicObject)
                {
                    var firstDO = first as System.Dynamic.DynamicObject;
                    var properties = firstDO.GetDynamicMemberNames();
 
                    foreach (var p in properties)
                    {
                        var pObject = GetDynamicMember(first, p);
                        var type = pObject.GetType();
                        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
                            type = type.GetGenericArguments()[0];
 
                        dt.Columns.Add(p, type);
                    }
 
                    foreach (T r in input)
                    {
                        var values = new object[properties.Count()];
                        int i = 0;
                        foreach (var p in properties)
                        {
                            values[i] = GetDynamicMember(r, p);                               
                            i++;
                        }
 
                        dt.LoadDataRow(values, true);
                    }
                }
 
            }
            else
            {
                // T is static type               
                var properties = typeof (T).GetProperties();
 
                foreach (var p in properties)
                {
                    var type = p.PropertyType;
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
                        type = type.GetGenericArguments()[0];
 
                    dt.Columns.Add(p.Name, type);
                }
 
                foreach (T r in input)
                {
                    var values = new object[properties.Length];
                    int i = 0;
                    foreach (var p in properties)
                    {
                        values[i] = p.GetValue(r, null);
                        i++;
                    }
 
                    dt.LoadDataRow(values, true);
                }
            }
            return dt;
        }
       
        //todo cache the callsite
        private static object GetDynamicMember( object obj, string memberName)
        {
            var binder = Binder .GetMember(CSharpBinderFlags.None, memberName, obj.GetType(),
                new[] { CSharpArgumentInfo .Create(CSharpArgumentInfoFlags.None, null) });
            var callsite = CallSite <Func< CallSite, object , object>>.Create(binder);
            return callsite.Target(callsite, obj);
        }

 


posted @ 2012-05-15 13:33  gunsmoke  阅读(170)  评论(0编辑  收藏  举报