具体使用
定义一个动态拼接lambda 的帮助类
using System.Linq.Expressions;
using System.Reflection;
namespace Utils
{
public class Filter
{
public string Key { get; set; } //过滤的关键字
public string Value { get; set; } //过滤的值
public string Contract { get; set; }// 过滤的约束 比如:'<' '<=' '>' '>=' 'like'等
}
public static class DynamicLinq
{
/// <summary>
/// 创建lambda中的参数,即c=>c.xxx==xx 中的c
/// </summary>
public static ParameterExpression CreateLambdaParam<T>(string name)
{
return Expression.Parameter(typeof(T), name);
}
/// <summary>
/// 创建linq表达示的body部分,即c=>c.xxx==xx 中的c.xxx==xx
/// </summary>
public static Expression GenerateBody<T>(this ParameterExpression param, Filter filterObj)
{
PropertyInfo property = typeof(T).GetProperty(filterObj.Key);
//组装左边
Expression left = Expression.Property(param, property);
//组装右边
Expression right = null;
//todo: 下面根据需要,扩展自己的类型
if (property.PropertyType == typeof(int))
{
right = Expression.Constant(int.Parse(filterObj.Value));
}
else if (property.PropertyType == typeof(short))
{
right = Expression.Constant(short.Parse(filterObj.Value));
}
else if (property.PropertyType == typeof(short))
{
right = Expression.Constant((short)short.Parse(filterObj.Value), typeof(short));
}
else if (property.PropertyType == typeof(DateTime?))
{
right = Expression.Constant((DateTime?)DateTime.Parse(filterObj.Value), typeof(DateTime?));
}
else if (property.PropertyType == typeof(DateTime))
{
right = Expression.Constant(DateTime.Parse(filterObj.Value));
}
else if (property.PropertyType == typeof(string))
{
right = Expression.Constant((filterObj.Value));
}
else if (property.PropertyType == typeof(decimal))
{
right = Expression.Constant(decimal.Parse(filterObj.Value));
}
else if (property.PropertyType == typeof(Guid))
{
right = Expression.Constant(Guid.Parse(filterObj.Value));
}
else if (property.PropertyType == typeof(bool))
{
right = Expression.Constant(filterObj.Value.Equals("1"));
}
else
{
throw new Exception("暂不能解析该Key的类型");
}
//todo: 下面根据需要扩展自己的比较
Expression filter = Expression.Equal(left, right);
switch (filterObj.Contract)
{
case "<=":
filter = Expression.LessThanOrEqual(left, right);
break;
case "==": //bool 类型
filter = Expression.Call(left, typeof(Boolean).GetMethod("Equals", new[] { typeof(Boolean) }),
Expression.Constant(filterObj.Value.Equals("1")));
break;
case "==="://string 类型
filter = Expression.Call(left, typeof(string).GetMethod("Equals", new[] { typeof(string) }),
Expression.Constant(filterObj.Value));
break;
case "==i": //int 类型
filter = Expression.Call(left, typeof(int).GetMethod("Equals", new[] { typeof(int) }),
Expression.Constant(Convert.ToInt32(filterObj.Value)));
break;
case "==is": //short 类型
filter = Expression.Call(left, typeof(short).GetMethod("Equals", new[] { typeof(short) }),
Expression.Constant(Convert.ToInt16(filterObj.Value)));
break;
case "<":
filter = Expression.LessThan(left, right);
break;
case ">":
filter = Expression.GreaterThan(left, right);
break;
case ">=":
filter = Expression.GreaterThanOrEqual(left, right);
break;
case "like":
filter = Expression.Call(left, typeof(string).GetMethod("Contains", new[] { typeof(string) }),
Expression.Constant(filterObj.Value));
break;
case "!=":
filter = Expression.NotEqual(left, Expression.Constant(filterObj.Value));
break;
}
return filter;
}
/// <summary>
/// 创建完整的lambda,即c=>c.xxx==xx
/// </summary>
public static LambdaExpression GenerateLambda(this ParameterExpression param, Expression body)
{
return Expression.Lambda(body, param);
}
/// <summary>
/// 创建完整的lambda,为了兼容EF中的where语句
/// </summary>
public static Expression<Func<T, bool>> GenerateTypeLambda<T>(this ParameterExpression param, Expression body)
{
return (Expression<Func<T, bool>>)(param.GenerateLambda(body));
}
public static Expression AndAlso(this Expression expression, Expression expressionRight)
{
return Expression.AndAlso(expression, expressionRight);
}
public static Expression Or(this Expression expression, Expression expressionRight)
{
return Expression.Or(expression, expressionRight);
}
public static Expression And(this Expression expression, Expression expressionRight)
{
return Expression.And(expression, expressionRight);
}
}
public static class DynamicExtention
{
public static IQueryable<T> Where<T>(this IQueryable<T> query, Filter[] filters)
{
var param = DynamicLinq.CreateLambdaParam<T>("c");
Expression body = Expression.Constant(true); //初始默认一个true
Expression bodykey; //初始默认一个true
foreach (var filter in filters)
{
body = body.AndAlso(param.GenerateBody<T>(filter)); //这里可以根据需要自由组合
}
var lambda = param.GenerateTypeLambda<T>(body); //最终组成lambda
return query.Where(lambda);
}
}
}
在方法中使用
List<Filter> filters = new List<Filter>();
filters.Add(new Filter { Key = "LastEditAt", Value = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd"), Contract = ">=" });
filters.Add(new Filter { Key = "Carrier", Value = HousingID, Contract = "like" });
filters.Add(new Filter { Key = "OperationNumberId", Value = option.ToString(), Contract = "==is" });
var area = _context.Tables.Where(filters.ToArray()).ToList();