本质上,您希望从 DataTable 中检索特定字段,而不对字段名称进行硬编码。
以下代码将每行返回一个字典对象,其中包含您在数组中指定的字段。无需创建额外的扩展方法或比较器:
var result = (from row in _dataTable.AsEnumerable()
let projection = from fieldName in fields
select new {Name = fieldName, Value = row[fieldName]}
select projection.ToDictionary(p=>p.Name,p=>p.Value));
内部选择从每个表格行中选择您需要的字段值并将它们存储在投影变量中。外部选择将此变量转换为字典
您可以遍历结果以获取特定字段,如下所示:
foreach (var row in result)
{
Console.WriteLine(row["field1"]);
}
编辑:
上面的代码不返回不同的值。使用 group by 可以在不编写特殊比较器的情况下返回不同的值,但代码不是很漂亮:
var result = (from row in table.AsEnumerable()
let projection = from fieldName in fields
select new { Name = fieldName, Value = row[fieldName] }
group projection by projection.Aggregate((v, p) =>
new {
Name = v.Name + p.Name,
Value = (object)String.Format("{0}{1}", v.Value, p.Value)
}) into g
select g.FirstOrDefault().ToDictionary(p=>p.Name,p=>p.Value));
聚合创建一个新的投影,其名称和值属性是所有名称和值字段的串联。聚合的结果用于对所有行进行分组并返回每个组的第一行。它有效,但它绝对是丑陋的。
最好创建一个简单的 DictionaryComparer,如下代码:
public class DictionaryComparer<TKey,TValue>: EqualityComparer<Dictionary<TKey,TValue>>
{
public override bool Equals(Dictionary<TKey, TValue> x, Dictionary<TKey, TValue> y)
{
//True if both sequences of KeyValuePair items are equal
var sequenceEqual = x.SequenceEqual(y);
return sequenceEqual;
}
public override int GetHashCode(Dictionary<TKey, TValue> obj)
{
//Quickly detect differences in size, defer to Equals for dictionaries
//with matching sizes
return obj.Count;
}
}
这允许你写:
var result = (from row in table.AsEnumerable()
let projection = from fieldName in fields
select new {Name = fieldName, Value = row[fieldName]}
select projection.ToDictionary(p=>p.Name,p=>p.Value))
.Distinct(new DictionaryComparer<string, object>());