Linq查询 - List <T>上的"Where"其中reflect属性包含text/value

Lig*_*ng3 1 c# linq expression-trees

我想构建一个函数,用户可以搜索列表中的某些属性是否包含值

假设我们将拥有List,并且Company将被定义为具有以下属性的类:

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string CompanyAddress1 { get; set; }
    public string CompanyPostCode { get; set; }
    public string CompanyCity { get; set; }
    public string CompanyCounty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在 - 理想情况下我希望有这个参数的功能

List<Company> FilterCompanies(List<Company> unfilteredList, string fieldToQueryOn, string query)
{
    // linq  version what ideally would like to archeve
    return unfilteredList.Where(x => x."fieldToQueryOn".ToString().ToLower().Contains(query.ToLower())).ToList();
}
Run Code Online (Sandbox Code Playgroud)

并致电:

var variable = FilterCompanies(NotNullFilledUnfilteredList, "CompanyCity", "New York")
Run Code Online (Sandbox Code Playgroud)

我尝试按照docs.microsoft.com上的教程进行操作,这很简单,但我不知道如何使用反射对类型扩展该解决方案并在表达式树中使用它.

Bac*_*cks 5

泛型和lambda:

namespace WhereTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var companies = new[] { new Company { Id = 1, Name = "abc" }, new Company { Id = 2, CompanyAddress1 = "abc" } };
            foreach (var company in FilterCompanies(companies, "abc", x => x.Name, x => x.CompanyCity))
            {
                Console.WriteLine(company.Id);
            }
        }

        static List<Company> FilterCompanies(IEnumerable<Company> unfilteredList, string query, params Func<Company, string>[] properties)
        {
            return unfilteredList.Where(x => properties.Any(c => c.Invoke(x) == query)).ToList();
        }
    }

    public class Company
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string CompanyAddress1 { get; set; }
        public string CompanyPostCode { get; set; }
        public string CompanyCity { get; set; }
        public string CompanyCounty { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

优点:无反射,强类型代码.


pok*_*oke 5

您可以使用Type.GetProperty反射通过名称查找属性,然后使用GetValue检索值:

List<Company> FilterCompanies(List<Company> list, string propertyName, string query)
{
    var pi = typeof(Company).GetProperty(propertyName);

    query = query.ToLower();
    return list
        .Where(x => pi.GetValue(x).ToString().ToLower().Contains(query))
        .ToList();
}
Run Code Online (Sandbox Code Playgroud)

您可能应该添加一些错误处理,以防有人使用无效的属性。例如,(pi?.GetValue(x) ?? string.Empty).ToString().ToLower()…为了安全起见,您可以这样做。

我还移出了query.ToLower()lambda 表达式以确保它只运行一次。您还可以尝试其他不区分大小写的方法来检查是否query是值的子字符串,以避免必须转换任何字符串。查看问题“不区分大小写的'包含(字符串)'”以获取更多信息。

顺便提一句。如果您通常对运行动态查询感兴趣,您应该看看动态 LINQ

  • 好的答案,而不是 ToLower,您可以使用 `OrdinalIgnoreCase` (2认同)