我有以下linq到对象查询:
from tb ItemTable
where tb.id =555
select new
{
field1=tb.field1,
field2=tb.field2,
..
..
..
fieldn=tb.fieldn
}
现在,所有这些字段都属于string
类型,我想知道是否有任何字段不包含子字符串" ab"。但我想知道我是否可以避免编写过滤器,如:
where (tb.field1.Contains("ab") == false) && (tb.field2.Contains("ab") == false) ...
所以我的问题是,有没有办法可以在不使用上述内容的情况下完成?
一切顺利
答案 0 :(得分:4)
由于您无法迭代未知类型的字段,因此需要使用Reflection
迭代字段来迭代它们:
(from tb ItemTable
where tb.id =555
select new
{
field1=tb.field1,
field2=tb.field2,
..
..
..
fieldn=tb.fieldn
})
.Where(item => !item.GetType().GetProperties()
.Where(propertyInfo => propertyInfo.PropertyType == typeof(string))
.Any(propertyInfo => ((string)propertyInfo.GetValue(item))
.Contains("ab"));
请注意,反射速度超慢 ,因此在应用程序中反复执行此类操作时,您应该更喜欢通过代码生成进行过滤
由于反射的性能,并且由于所有未知类型都是相同的,我们可以一次性获取属性,而不是一次又一次地获取它们:
var tableResults = (from tb ItemTable
where tb.id =555
select new
{
field1=tb.field1,
field2=tb.field2,
..
..
..
fieldn=tb.fieldn
})
IEnumerable<PropertyInfo> propertyInfos =
tableResults.FirstOrDefault()?.GetType().GetProperties()
.Where(propertyInfo => propertyInfo.PropertyType == typeof(string));
tableResults = tableResults
.Where(item => !propertyInfos
.Any(propertyInfo => ((string)propertyInfo.GetValue(item))
.Contains("ab")));
另外,如果可能的话,我会尝试避免未知类型,或者考虑将字段存储在Enumerable
中,如果它适合您的应用程序设计。