动态 属性 + Linq
Dynamic property + Linq
我有一个对象列表。我有一个过滤器值列表。我需要一个对象列表的计数,其中 field/property(在 运行 时通过变量指定)具有在过滤器列表中找到的值。顺便说一句,还有其他“过滤”属性,但这些 属性 名称是“固定的”,因此在构建时已知。
假设过滤器列表具有以下值:
橙色、黄色、蓝色
假设对象列表具有以下 properties/values:
Name: Bike, Color: Red |
Name: Car, Color: Green |
Name: Box, Color: Yellow |
Name: Door, Color: Orange |
“过滤字段”是在 运行 时定义为“颜色”的字符串变量 property/field。
结果应该是 2(盒子和门),因为列表中的其他对象没有在过滤器列表中找到的“颜色”。
这是我所拥有的并且它有效,但我正在寻找一种在 运行 时间动态指定“过滤字段”属性 名称(“Field1”)的方法。
total = (from objects in ObjectsObservableCollection where ((object.InCity && cityList.Select(ma => ma.CityText).Contains(objects.CityLabel)) && FilterValuesList.Select(ff => ff.ToString().ToUpper()).Contains(objects.**Field1**.ToString().ToUpper())) select objects.ID).Count();
我可以使用 switch-case(每个 属性 都有一个 select 语句)来确定哪个 属性 被用作 [=42 处的“过滤字段” =]-time(因为所有 属性 名称在 运行-time 都是已知的)但我真的很想了解如何以“正确的方式”做到这一点。
我认为表达式是正确的方法,但我无法理解语法。如果我正在搜索的是 1 个值(而不是值列表),我想我可以做到。
任何人都可以给我一个提示,也许指向一篇文章或教程,或者解释我需要用什么来完成这个?
如果您已经有一组固定的字段要测试,假设它们都是 string
字段,您可以创建一个 Dictionary
访问器 lambda,可以通过以下方式查找字段名称:
var FilterValues = FilterValueList.Select(s => s.ToLowerInvariant()).ToHashSet();
var TransportAccessorsDict = new[] {
new { FieldName = "Color", Accessor = (Func<Transport,String>)(t => t.Color) },
new { FieldName = "Name", Accessor = (Func<Transport,String>)(t => t.Name) },
}
.ToDictionary(fa => fa.FieldName, fa => fa.Accessor);
var getFilterField = TransportAccessorsDict[FilterField];
var total = (from objects in ObjectsObservableCollection
where FilterValues.Contains(getFilterField(objects).ToLowerInvariant())
select objects.ID
).Count();
这应该是合理的性能,但如果性能是一个重要的考虑因素,您可能应该将 FilterValuesList 转换为大写(我认为小写是首选,尽管两者都不好,文化感知字符串不敏感包含将是最好的) HashSet
在 LINQ 查询中使用它之前。
我删除了 ToString
调用,因为它们应该是多余的,否则你会有更大的(类型)问题。
我有一个对象列表。我有一个过滤器值列表。我需要一个对象列表的计数,其中 field/property(在 运行 时通过变量指定)具有在过滤器列表中找到的值。顺便说一句,还有其他“过滤”属性,但这些 属性 名称是“固定的”,因此在构建时已知。
假设过滤器列表具有以下值:
橙色、黄色、蓝色
假设对象列表具有以下 properties/values:
Name: Bike, Color: Red |
Name: Car, Color: Green |
Name: Box, Color: Yellow |
Name: Door, Color: Orange |
“过滤字段”是在 运行 时定义为“颜色”的字符串变量 property/field。
结果应该是 2(盒子和门),因为列表中的其他对象没有在过滤器列表中找到的“颜色”。
这是我所拥有的并且它有效,但我正在寻找一种在 运行 时间动态指定“过滤字段”属性 名称(“Field1”)的方法。
total = (from objects in ObjectsObservableCollection where ((object.InCity && cityList.Select(ma => ma.CityText).Contains(objects.CityLabel)) && FilterValuesList.Select(ff => ff.ToString().ToUpper()).Contains(objects.**Field1**.ToString().ToUpper())) select objects.ID).Count();
我可以使用 switch-case(每个 属性 都有一个 select 语句)来确定哪个 属性 被用作 [=42 处的“过滤字段” =]-time(因为所有 属性 名称在 运行-time 都是已知的)但我真的很想了解如何以“正确的方式”做到这一点。
我认为表达式是正确的方法,但我无法理解语法。如果我正在搜索的是 1 个值(而不是值列表),我想我可以做到。
任何人都可以给我一个提示,也许指向一篇文章或教程,或者解释我需要用什么来完成这个?
如果您已经有一组固定的字段要测试,假设它们都是 string
字段,您可以创建一个 Dictionary
访问器 lambda,可以通过以下方式查找字段名称:
var FilterValues = FilterValueList.Select(s => s.ToLowerInvariant()).ToHashSet();
var TransportAccessorsDict = new[] {
new { FieldName = "Color", Accessor = (Func<Transport,String>)(t => t.Color) },
new { FieldName = "Name", Accessor = (Func<Transport,String>)(t => t.Name) },
}
.ToDictionary(fa => fa.FieldName, fa => fa.Accessor);
var getFilterField = TransportAccessorsDict[FilterField];
var total = (from objects in ObjectsObservableCollection
where FilterValues.Contains(getFilterField(objects).ToLowerInvariant())
select objects.ID
).Count();
这应该是合理的性能,但如果性能是一个重要的考虑因素,您可能应该将 FilterValuesList 转换为大写(我认为小写是首选,尽管两者都不好,文化感知字符串不敏感包含将是最好的) HashSet
在 LINQ 查询中使用它之前。
我删除了 ToString
调用,因为它们应该是多余的,否则你会有更大的(类型)问题。