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

发布于 2024-10-02 12:28:24 字数 253 浏览 2 评论 0原文

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

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

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

我想要一个方法,可以迭代员工集合中的所有员工,并返回名字或姓氏缺失的员工集合,即 null 或空字符串。

将 .NET 3.5 与 C# 结合使用

I have a collection of objects (IQueryable). Each object has various properties, some string some datetime, I'm not concerned about the datetime properties. How can I iterate through each object and return a collection of those objects that maybe have null values in one or more fields

For simplicity, consider a collection of Employees

Each employee may have two properties:
FirstName (string)
LastName (string)

I'd like to have a method that could iterate through all employees in the employee collection and return a collection of employees that either have first name or last name missing, i.e null or an empty string.

using .NET 3.5 with C#

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ˇ宁静的妩媚 2024-10-09 12:28:24

这应该可以帮助您开始:

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 的具体类(明显的接口方法是 bool IsSatisfiedBy(T实体)),然后

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

This should get you started:

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

It's clear how to generalize this using generics.

Even better is to just have a concrete class that implements some interface ISpecification<T> (obvious interface method is bool IsSatisfiedBy(T entity)) and then

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

For example:

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

Then you can say:

// IEnumerable<Employee> employees;
// EmployeeSpecification specification;
var invalidEmployees = employees.GetInvalidEntitites(specification);
烟酉 2024-10-09 12:28:24
Employees.Where(e => string.IsNullOrEmpty(e.FirstName) || string.IsNullOrEmpty(e.LastName))
Employees.Where(e => string.IsNullOrEmpty(e.FirstName) || string.IsNullOrEmpty(e.LastName))
三岁铭 2024-10-09 12:28:24

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

即可迭代 Employee 集合。检查当前 Employee 是否有空值(或任何其他特征),然后将它们添加到“invalidEmployees”集合中。

Simply create a second collection "invalidEmployees"

Iterate through Employee collection. Check current Employee for null values (or any other characteristic) then add them to the "invalidEmployees" collection.

梦里人 2024-10-09 12:28:24

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

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

If I understand the question, the solution should be pretty trivial:

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

where the iQuaryable is the instance of your IQuaryable implementation.

带刺的爱情 2024-10-09 12:28:24

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

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

Do you want to explicitly state which fields for which your method will check the objects?
Or do you want all string properties checked?
Or are the properties static and known at compile time?
Are the objects all the same type?

It could be as simple as a where clause like shown in other answers:

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

Or it could be as complex as specifying the string property names you want to check and iterating them:

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

Callable with something like:

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

You could further cut down on the number of properties you check against if you pre-filter for string types. After the GetProperties() add

.Where(prop => prop.GetType() == typeof(string));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文