将列表转换为DataTable时获取匿名类型

时间:2018-09-27 18:12:19

标签: c#

我有一个列表,我在其中选择列TaskId(全局变量)和EmpGuid(从列表),例如:

 var parameterstest = assignNotificationTableType.Select(x => new { TaskId, x.EmpGuid }).ToList();

所以,如果我调试,我会得到类似的东西:

enter image description here

现在,我创建了将其转换为DataTable的方法,

public static DataTable ToDataTable<T>(List<T> items)
        {

            DataTable dataTable = new DataTable(typeof(T).Name);

            //Get all the properties

            PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            if (Props.Length > 0)
            {
                foreach (PropertyInfo prop in Props)
                {
                    if (GetDefault(prop.PropertyType.FullName) != null)
                    {
                        //Setting column names as Property names
                        dataTable.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
                    }
                }
            }
            else
            {
                dataTable.Columns.Add("myColName");
            }
            foreach (T item in items)
            {
                if (item != null)
                {
                    DataRow dr = dataTable.NewRow();
                    if (Props.Length > 0)
                    {
                        foreach (PropertyInfo prop in Props)
                        {
                            if (GetDefault(prop.PropertyType.FullName) != null)
                            {
                                //inserting property values to datatable rows
                                dr[prop.Name] = prop.GetValue(item, null) ?? GetDefault(prop.PropertyType.FullName);
                            }
                        }
                    }
                    else
                    {
                        //inserting property values to datatable rows
                        dr[0] = item;
                    }

                    dataTable.Rows.Add(dr);
                }
            }

            //put a breakpoint here and check datatable

            return dataTable;

        }

        public static object GetDefault(string dataType)
        {

            if (dataType.Contains("System.String"))
            {
                return string.Empty;
            }
            if (dataType.Contains("System.Boolean"))
            {
                return false;
            }
            if (dataType.Contains("System.Decimal"))
            {
                return 0.0;
            }
            if (dataType.Contains("System.DateTime"))
            {
                return DateTime.MinValue;
            }
            if (dataType.Contains("System.Int64"))
            {
                return 0;
            }
            if (dataType.Contains("System.Guid"))
            {
                return null;
            }
            if (dataType.Contains("System.Int16"))
            {
                return 0;
            }
            if (dataType.Contains("Int32"))
            {
                return 0;

            }
            if (dataType.Contains("System.Object"))
            {
                return null;
            }

            return null;
        }

但是当我尝试用作:

 var parameters = ToDataTable(assignNotificationTableType.Select(x => new { TaskId, x.EmpGuid }).ToList());

变量返回{<>f__AnonymousType42}而不是数据表

enter image description here

我不知道为什么它返回AnonymousType。有人知道那里是什么问题吗?

更新

enter image description here

如您所见,匿名类型数据表正确计数了行,但ItemArray始终为零而不是我的值

2 个答案:

答案 0 :(得分:0)

我解决了将我的Convert DataTable方法更改为:

public static DataTable ToSingleDataTable<T>(IList<T> data)
        {
            PropertyDescriptorCollection props =
                TypeDescriptor.GetProperties(typeof(T));
            DataTable table = new DataTable();
            for (int i = 0; i < props.Count; i++)
            {
                PropertyDescriptor prop = props[i];
                table.Columns.Add(prop.Name, prop.PropertyType);
            }
            object[] values = new object[props.Count];
            foreach (T item in data)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    values[i] = props[i].GetValue(item);
                }
                table.Rows.Add(values);
            }
            return table;
        }

答案 1 :(得分:-1)

使用dynamic变量,C#编译器添加代码以找出变量的类型并在运行时对其进行必要的操作。

C#中的泛型在编译时已得到验证;也就是说,如果您拥有List<T>并使用new List<int>()进行构造,则在编译阶段会生成一个新的完全类(我相信为“ List`1 [Int32]”)并将其包含在二进制文件。调用new List<int>()将被该新类的构造函数替换(与Java进行对比,Java会对类的泛型进行类型擦除,而不是对类型进行类型化,因此,所有内容最终都包含了{{1} },实际上是ArrayList)。

也许您看到了进展。要编译创建Object的函数,编译器必须在编译时知道ArrayList<Object> 的类型-正是DataTable<T>告诉编译器要执行的操作推迟并在运行时找出。因此,每次您说TdynamicDataTable<T>时,编译器都必须放置一个占位符:即AnonymousType。调试器对此一无所知,因为调试符号也是在编译时添加的。

如果您无法通过单击显示三角形查看数据表中包含的项目,那么如果您使用T和/或{{1转到调试器命令行,则仍然可以查看它们}}等