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

testing field values of an anonymous type in a generic way

我有以下 linq to object 查询:

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) ...

所以我的问题是,有什么方法可以不使用上述方法来完成吗?

祝一切顺利

由于您无法迭代未知类型的字段,这将需要您使用 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 中(如果它适合您的应用程序设计)。