迭代集合项并检查每个属性的有效值

时间:2010-11-10 21:42:31

标签: c# .net linq collections

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

为简单起见,请考虑一组Employees

每位员工可能有两个属性: FirstName(字符串) LastName(字符串)

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

将.NET 3.5与C#一起使用

5 个答案:

答案 0 :(得分:2)

这应该让你开始:

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

答案 1 :(得分:1)

Employees.Where(e => string.IsNullOrEmpty(e.FirstName) || string.IsNullOrEmpty(e.LastName))

答案 2 :(得分:0)

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

通过Employee集合进行迭代。检查当前Employee的空值(或任何其他特征),然后将它们添加到“invalidEmployees”集合中。

答案 3 :(得分:0)

如果我理解这个问题,解决方案应该是非常简单的:

  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实现的实例。

答案 4 :(得分:0)

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

它可以像其他答案中所示的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));