我有一个列表,我在其中选择列TaskId
(全局变量)和EmpGuid
(从列表),例如:
var parameterstest = assignNotificationTableType.Select(x => new { TaskId, x.EmpGuid }).ToList();
所以,如果我调试,我会得到类似的东西:
现在,我创建了将其转换为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}
而不是数据表
我不知道为什么它返回AnonymousType。有人知道那里是什么问题吗?
更新
如您所见,匿名类型数据表正确计数了行,但ItemArray始终为零而不是我的值
答案 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>
告诉编译器要执行的操作推迟并在运行时找出。因此,每次您说T
时dynamic
是DataTable<T>
时,编译器都必须放置一个占位符:即AnonymousType。调试器对此一无所知,因为调试符号也是在编译时添加的。
如果您无法通过单击显示三角形查看数据表中包含的项目,那么如果您使用T
和/或{{1转到调试器命令行,则仍然可以查看它们}}等