如何将Dictionary的LINQ表达式扩展为参数

时间:2013-09-05 02:27:31

标签: c# linq

我有这个程序,我扩展LINQ表达式以使用任何属性名称和值作为参数获得结果。我的扩展程序只适用于一个属性但是我需要查找并传递两个或多个属性作为过滤器。任何人都可以帮我扩展我的LINQ吗?以下是我的代码实现。我使用了控制台应用程序。

根据我刚才调用的用户列表的示例代码

GetByPropertyName("PropertyName", "Value");

例如

var user = GetByPropertyName("FirstName", "James");

Program.cs的

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static List<User> _users = new List<User>();
        static void Main(string[] args)
        {
            var users = new List<User> { 
                new User { FirstName = "John", MiddleName = "Hall", LastName = "Long", Email="john.long@gmail.com"}, 
                new User { FirstName = "John", MiddleName = "Wine", LastName = "Crawford", Email="john.crawford@gmail.com" }, 
                new User { FirstName = "James", MiddleName = "Cage", LastName = "Hall", Email="james.hall@hotmail.com" }, 
                new User { FirstName = "Larry", MiddleName = "Wine", LastName = "Crawford", Email="larry.crawford@gmail.com" },
                new User { FirstName = "Jennifer", MiddleName = "Wine", LastName = "Long", Email="jennifer.long@gmail.com"} 
            };
            //works okay for one property name
            _users = users;
            var user = GetByPropertyName("FirstName", "James");

            //works okay for one property name
            _users = users;
            var user1 = GetByPropertyName("Email", "james.hall@hotmail.com");

            //NEED HELP
            //For GetByPropertyNames two or more properties
            var filters = new Dictionary<object, object>();
            filters.Add("FirstName", "John");
            filters.Add("Email", "john.long@gmail.com");
            var user2 = GetByPropertyNames(filters);
        }
        public static User GetByPropertyName(object propertyName, object value)
        {
            var result = _users.AsQueryable().Where(propertyName.ToString(), value).FirstOrDefault();
            return result;
        }

        public static User GetByPropertyNames(Dictionary<object, object> filters)
        {
            var result = _users.AsQueryable().Where(filters).FirstOrDefault();
            return null;
        }
    }
    public class User 
    {
        public string FirstName { get; set; }
        public string MiddleName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
    }
}

Extensions.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace ConsoleApplication1
{
    public static class Extensions {
        public static IQueryable<T> Where<T>(this IQueryable<T> source, string propertyName, object value) {
            return (IQueryable<T>)Where((IQueryable)source, propertyName, value);
        }

        public static IQueryable Where(this IQueryable source, string propertyName, object value) {
            var x = Expression.Parameter(source.ElementType, "x");
            var selector = Expression.Lambda(
                Expression.Equal(
                    Expression.PropertyOrField(x, propertyName),
                    Expression.Constant(value)
                ), x
            );

            return source.Provider.CreateQuery(
                Expression.Call(typeof(Queryable), "Where", new Type[] { source.ElementType }, source.Expression, selector)
            );
        }

        //NEED HELP
        //TO DO
        public static IQueryable<T> Where<T>(this IQueryable<T> source, Dictionary<object, object> filters)
        {
            return (IQueryable<T>)Where((IQueryable)source, filters);
        }

        public static IQueryable Where(this IQueryable source, Dictionary<object, object> filters)
        {
            var x = Expression.Parameter(source.ElementType, "x");
            //NEED HELP
            //expression for _users.FirstOrDefault(x=>x.Filter1==Filter1Value && x.Filter2==Filter2Value && so on and so fort depends on how many filters are passed as arguments);

            //var selector = Expression.Lambda(
            //    Expression.Equal(
            //        Expression.PropertyOrField(x, propertyName),
            //        Expression.Constant(value)
            //    ), x
            //);

            //return source.Provider.CreateQuery(
            //    Expression.Call(typeof(Queryable), "Where", new Type[] { source.ElementType }, source.Expression, selector)
            //);

            //remove line below
            return null;
        }

    }
}

1 个答案:

答案 0 :(得分:1)

删除IQueryable Where(this IQueryable source, Dictionary<object, object> filters)并更新您的通用版本,如下所示:

public static IQueryable<T> Where<T>(this IQueryable<T> source, Dictionary<object, object> filters)
{
    foreach (var kv in filters)
    {
        source = source.Where(kv.Key.ToString(), kv.Value);
    }
    return source;
}

添加多个Where()语句意味着AND逻辑。如果你想要OR逻辑会更痛苦。