如何在列表中搜索包含任何属性值中的子字符串的元素?

Pin*_*aas 3 c# lambda list

我试图在具有很多属性的对象列表中进行搜索.寻找一个优雅的解决方案,例如lambda表达式,它可以根据搜索字符串返回结果.这是我的简化数据源.我的实际Customer课程有更多属性:

public static class CustomerDataSource
{
    public static List<Customer> customerData
    {
        get
        {
            Customer customer1 = new Customer() { name = "Bert", address = "London" };
            Customer customer2 = new Customer() { name = "Jon", address = "New York" };
            List<Customer> listCustomers = new List<Customer>();
            listCustomers.Add(customer1);
            listCustomers.Add(customer2);
            return listCustomers;
        }
    }
}

public class Customer
{
    public string name { get; set; }
    public string address { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

什么样的语句可以返回Customer包含'searchstring'的所有s.例如,如果搜索字符串为'e',则它应返回两者customer1,customer2因为包含'e' 的nameaddress属性customer1.

我可以编写类似下面的内容,但后来我必须为每个属性编写一行代码:

var list = CustomerDataSource.customerData.FindAll(x => x.address.Contains("e"));
var list2 = CustomerDataSource.customerData.FindAll(x => x.name.Contains("e"));
Run Code Online (Sandbox Code Playgroud)

Kon*_*osa 6

您可以使用Reflection获取所有属性并将其与LINQ结合使用:

var list = CustomerDataSource
           .customerData
           .Where(c => c.GetType()
                        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                        .Any(pi => pi.GetValue(c).ToString().Contains("York")))
           .ToList();
Run Code Online (Sandbox Code Playgroud)

以上代码仅返回customer2.

但是,如果您现在想要在查询期间搜索所有属性,我会采用归因方法 - 使用您的自定义属性标记要搜索的属性:

[AttributeUsage(AttributeTargets.Property)]
sealed class SearchableAttribute : Attribute
{
    public SearchableAttribute()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

然后相应地修改您的类,例如,标记只name应该使用:

public class Customer
{
    [Searchable]
    public string name { get; set; }
    public string address { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

并略微修改上面的LINQ查询:

var list = CustomerDataSource
           .customerData
           .Where(c => c.GetType()
                        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                        .Where(pi => pi.GetCustomAttribute<SearchableAttribute>() != null)
                        .Any(pi => pi.GetValue(c).ToString().Contains("York")))
           .ToList();
Run Code Online (Sandbox Code Playgroud)

注意:正如Sam所说,aboce代码假定您对具有适当.ToString()实现类型的属性感兴趣.因此,在数组的情况下它不会起作用.您必须进一步修改此代码以满足您的需求.以下是使用合适.ToString()方法对数组进行额外处理的示例:

var list = CustomerDataSource
           .customerData
           .Where(c => c.GetType()
           .GetProperties(BindingFlags.Instance | BindingFlags.Public)
           .Where(pi => pi.GetCustomAttribute<SearchableAttribute>() != null)
           .Any(pi => pi.PropertyType.IsArray 
                          ? (pi.GetValue(c) as IEnumerable<object>)
                               .Any(o => o.ToString().Contains("Paris"))
                          : pi.GetValue(c).ToString().Contains("Paris")))
Run Code Online (Sandbox Code Playgroud)