从列表值动态创建匿名对象
本文关键字:对象 创建 动态 列表 | 更新日期: 2023-09-27 18:10:34
我有一个字符串列表(或者可以是数组),我想动态地创建一个匿名对象。我该怎么做呢?
var dataSet = new DataSet();
dataSet.ReadXml(@"");
var dataTable = dataSet.Tables[0];
var dataRow = dataTable.Rows[0];
var keys = new List<string> {"Column1","Column2"};
var result = new {keys[0] = dataRow[keys[0]], keys[1] = dataRow[keys[1]]}
所以这个名为"keys"的列表将在这个方法之外创建并且可以包含1到多个值。我试着创建一个字典,通过列表循环,并将键/值对添加到字典中,但后来我不知道如何将字典转换回匿名类型。我也尝试了扩展对象,但这似乎没有让我走得更远。
我必须能够返回一个匿名类型,因为这个方法的结果将与LINQ查询的GroupBy子句一起使用。
下面是动态创建字典的方法:
public object Key(DataRow dataRow, List<String> keys)
{
var dictionary = new IDictionary<string, object>;
foreach (string key in keys)
{
dictionary.Add(key, dataRow[key]);
}
return dictionary;
}
下面是我的LINQ查询:
var duplicates = dataTable.AsEnumerable().GroupBy(r => Key(r, keys)).Where(c => c.Count() > 1).ToList();
如果我从Key()方法中硬编码一个匿名类型,则GroupBy子句可以工作。基本上,我只需要根据键列表中的值动态设置GroupBy子句。
剥离你的问题,你想要的是能够根据一个运行时属性对项目列表进行分组,该属性可以由该项目的一个或多个属性组成。本质上,这意味着您需要一个选择器函数(即您的Key
方法)来将项转换为键。
为了使GroupBy工作,它需要能够比较任意两个键的实例,以查看它们是否相等。这意味着密钥需要实现一个有意义的Equals()
方法,或者您需要一个IEqualityComparer
实现来为您完成工作。在这种情况下,我不需要创建新的Key,只需编写一个可以直接比较两个datarow的相等比较器:
var duplicates = dataTable
.AsEnumerable()
.GroupBy(r => r, new MyDataRowComparer(keys))
.Where(c => c.Count() > 1)
.ToList();
internal class MyDataRowComparer : IEqualityComparer<DataRow>
{
private readonly string[] _keys;
public MyDataRowComparer(string[] keys)
{
_keys = keys; // keep the keys to compare by.
}
public bool Equals(DataRow x, DataRow y)
{
// a simple implementation that checks if all the required fields
// match. This might need more work.
bool areEqual = true;
foreach (var key in _keys)
{
areEqual &= (x[key] == y[key]);
}
return areEqual;
}
public int GetHashCode(DataRow obj)
{
// Add implementation here to create an aggregate hashcode.
}
}