Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
680 views
in Technique[技术] by (71.8m points)

c# - How can I send where statements to a method which are dynamically executed in a LINQ statement?

In the following example, GetFilteredCustomers() works fine so I can send various letters which I want customers to have in their last name.

But how can I build GetFilteredCustomersDynamic() which will enable me to send a full where clause that can be dynamically included in the LINQ statement?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestDynamicLinq2343
{
    public class Program
    {
        static void Main(string[] args)
        {
            List<Customer> customers = Customer.GetCustomers();

            //semi-dynamic
            foreach (var customer in Customer.GetFilteredCustomers(customers,  "o"))
            {
                Console.WriteLine(customer.LastName);
            }

            //fully-dyanmic (can send where clauses)
            foreach (var customer in Customer.GetFilteredCustomersDynamic(customers, c => c.FirstName.Contains("a")))
            {
                Console.WriteLine(customer.LastName);
            }

            Console.ReadLine();
        }
    }

    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Street { get; set; }
        public string Location { get; set; }
        public string ZipCode { get; set; }

        public static List<Customer> GetCustomers()
        {
            List<Customer> customers = new List<Customer>();
            customers.Add(new Customer { FirstName = "Jim", LastName = "Jones" });
            customers.Add(new Customer { FirstName = "Joe", LastName = "Adams" });
            customers.Add(new Customer { FirstName = "Jake", LastName = "Johnson" });
            return customers;
        }

        public static List<Customer> GetFilteredCustomers(List<Customer> customers, string letter)
        {
            return (from c in customers
                    where c.LastName.Contains(letter)
                    select c).ToList();
        }

        public static List<Customer> GetFilteredCustomersDynamic(List<Customer> customers, Func<..., bool> whereClause)
        {
            return (from c in customers
                    where ...whereClause...
                    select c).ToList();
        }

    }
}

Answer:

thanks elder_george and arjuns, I got this example to work like this (albeit without the Expression<> ):

using System;
using System.Collections.Generic;
using System.Linq;

namespace TestDynamicLinq2343
{
    public class Program
    {
        static void Main(string[] args)
        {
            List<Customer> customers = Customer.GetCustomers();

            Func<Customer, bool> whereClause = c => c.LastName.Contains("a") && c.FirstName.Contains("J");

            foreach (var customer in Customer.GetFilteredCustomers(customers, whereClause))
            {
                Console.WriteLine(customer.LastName);
            }

            Console.ReadLine();
        }
    }

    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Street { get; set; }
        public string Location { get; set; }
        public string ZipCode { get; set; }

        public static List<Customer> GetCustomers()
        {
            List<Customer> customers = new List<Customer>();
            customers.Add(new Customer { FirstName = "Jim", LastName = "Jones" });
            customers.Add(new Customer { FirstName = "Joe", LastName = "Adams" });
            customers.Add(new Customer { FirstName = "Jake", LastName = "Johnson" });
            customers.Add(new Customer { FirstName = "Angie", LastName = "Reckar" });
            customers.Add(new Customer { FirstName = "Jean-Luc", LastName = "Beaudoir" });
            return customers;
        }

        public static List<Customer> GetFilteredCustomers(List<Customer> customers, Func<Customer, bool> whereClause)
        {
            return customers
                   .Where(whereClause).ToList();
        }

    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You'd need to represent filter as Expression<Func<Customer, bool>>, not as Func<Customer, bool>. This way you can use Queryable.Where method to add this filter to LINQ expression tree.

EDIT: I was wrong, as this code uses LINQ to objects, where delegates are proper filter criteria. My bad.

E.g. (corrected to using normal delegates):

    public static List<Customer> GetFilteredCustomersDynamic(List<Customer> customers, Func<Customer, bool> whereClause)
    {
        return customers
               .Where(whereClause).ToList();
    }

    public static List<Customer> GetFilteredCustomers(List<Customer> customers, string letter)
    {
        return GetFilteredCustomersDynamic(c => c.LastName.Contains(letter));
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...