以通用方式测试匿名类型的字段值

时间:2015-12-04 12:03:58

标签: c# .net linq anonymous-types

我有以下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) ...

所以我的问题是,有没有办法可以在不使用上述内容的情况下完成?

一切顺利

1 个答案:

答案 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中,如果它适合您的应用程序设计。