遍历集合项并检查每个属性的有效值

Posted

技术标签:

【中文标题】遍历集合项并检查每个属性的有效值【英文标题】:Iterating through collection items and checking each property for a valid value 【发布时间】:2010-11-10 21:42:31 【问题描述】:

我有一个对象集合 (IQueryable)。每个对象都有各种属性,一些字符串一些日期时间,我不关心日期时间属性。如何遍历每个对象并返回可能在一个或多个字段中具有空值的那些对象的集合

为简单起见,考虑一组员工

每个员工可能有两个属性: 名字(字符串) 姓氏(字符串)

我希望有一个方法可以遍历员工集合中的所有员工并返回缺少名字或姓氏的员工集合,即 null 或空字符串。

将 .NET 3.5 与 C# 结合使用

【问题讨论】:

你应该更具体,使用反射? 【参考方案1】:

这应该让你开始:

var properties = typeof(Employee).GetProperties()
                                 .Where(p => p.PropertyType == typeof(string));
foreach(var employee in employees) 
    foreach(var property in properties) 
         string value = (string)property.GetValue(employee, null);
         if(String.IsNullOrWhiteSpace(value)) 
             yield return employee;
             break;
         
    

很清楚如何使用泛型来概括这一点。

更好的是只有一个具体的类来实现一些接口ISpecification<T>(明显的接口方法是bool IsSatisfiedBy(T entity))然后

public static IEnumerable<T> GetInvalidEntities<T>(
    this IEnumerable<T> source,
    ISpecification<T> specification
) 
    return source.Where(x => !specification.IsSatisfiedBy(x));

例如:

public class EmployeeSpecification : ISpecification<Employee> 
    public bool IsSatisfiedBy(Employee entity) 
        Contract.Requires<ArgumentNullException>(entity != null);
        return !String.IsNullOrWhiteSpace(entity.FirstName) &&
               !String.IsNullOrWhiteSpace(entity.LastName);
    

那么你可以说:

// IEnumerable<Employee> employees;
// EmployeeSpecification specification;
var invalidEmployees = employees.GetInvalidEntitites(specification);

【讨论】:

我认为这个问题只有两个属性(名字和姓氏),应该满足空字符串 @Jakub Konecki:不,Employee 只是一个例子。我认为他正在寻找更通用的东西。 哦,我明白了。然后反射是一个好方法 - 您可能希望通过检查属性类型(字符串)和空字符串作为值来扩展您的第一个代码示例 或 Func 而不是 ISpecification【参考方案2】:
Employees.Where(e => string.IsNullOrEmpty(e.FirstName) || string.IsNullOrEmpty(e.LastName))

【讨论】:

"为简单起见...." 这适用于非常具体的情况,并没有说明如何着手解决更普遍的问题。 @Jason,我强烈希望在代码中静态编写验证检查,而不是更通用的方法,以其他形式指定条件。无论哪种方式,您都以某种方式对检查进行编码并将其编写为明确定义的业务层中的简单代码,这比更全面的架构更易于维护。 @Dan Bryant:不同意。规范是可重用的,嵌入式验证检查不是。将验证检查与验证机制分离比您建议的更易于维护。【参考方案3】:

只需创建第二个集合“invalidEmployees”

遍历 Employee 集合。检查当前员工的空值(或任何其他特征),然后将它们添加到“invalidEmployees”集合中。

【讨论】:

【参考方案4】:

如果我理解这个问题,解决方案应该很简单:

  IEnumerable<Employee> collection = iQuaryable.AsEnumerable();
  List<Employee> myCollection = new List<Employee>();

  foreach(var emp in collection) 
  
        if(string.IsNullOrEmpty(emp.LastName) || string.IsNullOrEmpty(emp.FirstName))
             myCollection.Add(emp);
  

其中 iQuaryable 是您的 IQuaryable 实现的实例。

【讨论】:

【参考方案5】:

您想明确说明您的方法将检查对象的哪些字段? 还是要检查所有字符串属性? 或者属性是静态的并且在编译时是已知的? 对象都是同一类型吗?

它可以像其他答案中所示的 where 子句一样简单:

var nullPropItems = objectCollection.Where(ob => string.IsNullOrEmpty(ob.Property));

或者它可能像指定要检查的字符串属性名称并对其进行迭代一样复杂:

public static IEnumerable<T> HasNullStringProperties<T>(this IEnumerable<T> items, params string[] propertyNames)

    var properties = items.GetType().GetGenericArguments()[0].GetProperties();

    foreach(var item in items)
        foreach(string propertyName in propertyNames)
        
            var propertyInfo = properties.SingleOrDefault(p => p.Name.Equals(propertyName));
            if (null != propertyInfo)
            
                if (string.IsNullOrEmpty(propertyInfo.GetValue(item, null) as string))
                    yield return item;
            
        

可通过以下方式调用:

var items = objectCollection.HasNullStringProperties("FirstName", "LastName", "OrganizationName");

如果您预先过滤字符串类型,您可以进一步减少检查的属性数量。在 GetProperties() 之后添加

.Where(prop => prop.GetType() == typeof(string));

【讨论】:

以上是关于遍历集合项并检查每个属性的有效值的主要内容,如果未能解决你的问题,请参考以下文章

jquery如何遍历一个html页面标题生成目录

更好/更快地循环遍历集合或列表?

遍历节点树

freemarker可以用来输出自定义集合吗?

如何遍历集合属性

检查一组集合中的重复项的更有效方法是啥