LINQ 中动态属性名称

9

我想写一个 LINQ 查询,可以使用动态属性名称。例如,如果属性名是“test”,则简单查询如下:

var test = testList.Select(x => x.test).Distinct().ToList();

但是我希望能够动态生成属性名称,例如:
var propertyName = "test";

var test = testList.Select(x => x.propertyName).Distinct().ToList();

我因为“propertyName”不是一个真正的属性而收到错误提示。

最好的方法是什么?


3
你不能这样做。如果testList中充满了ExpandoObjects(不推荐),你可以将它们强制转换为 IDictionary<String, Object>并使用字符串进行索引。你也可以使用反射(也不是特别推荐)。但是你很可能不需要这样做。你使用这个LINQ查询解决什么问题? - 15ee8f99-57ff-4f92-890c-b56153
哦,另外你可以使用 Expression<Func<T>> 或其他方式构建一个属性选择器 lambda。我不确定这是否是推荐的方法,但可能比其他方法更好。 - 15ee8f99-57ff-4f92-890c-b56153
1
感谢回复,我可能走了一条错误的路。我只是想提取类似于此链接中的属性唯一值列表 - https://dev59.com/dWkv5IYBdhLWcg3w6lHj 但是有几个属性和类需要这样做。我希望动态生成属性名称以避免重复代码。 - richard
那是值得考虑的情况。你知道吗,其me386反射代码的某种赞美版本可能是最好的选择。我会编写一个lambda for循环来查找该属性,如果缺少,则引发比NullReference更具体和信息丰富性的异常。 - 15ee8f99-57ff-4f92-890c-b56153
1个回答

20

您需要使用反射来完成您正在尝试的操作:

var test = testList
               .Select(x => x.GetType().GetProperty(propertyName).GetValue(x))
               .Distinct()
               .ToList();

3
当然,使用这种方法你将失去所有的类型检查,所以容易出现严重的错误。 - DavidG
此外,这不是同一件事,它返回一个“object”的枚举,而原始代码是特定类型的。 - DavidG
@DavidG 那是个好观点。我猜如果你知道所有属性的返回类型,你可以在 .Distinct() 之前添加 .Cast<whatevertype>() 或者只需转换 GetValue() 返回的对象。像 @EdPlunkett 建议的那样构建表达式可能更加类型安全。 - itsme86
1
太棒了!它有效了,我按照你说的添加了.Cast<String>(),这对我需要它做的事情来说很好。 - richard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接