// ***********************************************************************
// Assembly : FairUtility
// Author : Yubao Li
// Created : 08-18-2015
//
// Last Modified By : Yubao Li
// Last Modified On : 08-18-2015
// ***********************************************************************
//
// Copyright (c) . All rights reserved.
//
// 动态linq
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using SqlSugar;
namespace Infrastructure
{
public static class DynamicLinq
{
public static ParameterExpression CreateLambdaParam(string name)
{
return Expression.Parameter(typeof(T), name);
}
///
/// 创建linq表达示的body部分
///
public static Expression GenerateBody(this ParameterExpression param, Filter filterObj)
{
PropertyInfo property = typeof(T).GetProperty(filterObj.Key);
Expression left = null; //组装左边
//组装右边
Expression right = null;
if (property != null)
{
left = Expression.Property(param, property);
if (property.PropertyType == typeof(int))
{
right = Expression.Constant(int.Parse(filterObj.Value));
}
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 if (property.PropertyType == typeof(Guid?))
{
left = Expression.Property(left, "Value");
right = Expression.Constant(Guid.Parse(filterObj.Value));
}
else
{
throw new Exception("暂不能解析该Key的类型");
}
}
else //如果左边不是属性,直接是值的情况
{
left = Expression.Constant(filterObj.Key);
right = Expression.Constant(filterObj.Value);
}
//c.XXX=="XXX"
Expression filter = Expression.Equal(left, right);
switch (filterObj.Contrast)
{
case "<=":
filter = Expression.LessThanOrEqual(left, right);
break;
case "<":
filter = Expression.LessThan(left, right);
break;
case ">":
filter = Expression.GreaterThan(left, right);
break;
case ">=":
filter = Expression.GreaterThanOrEqual(left, right);
break;
case "!=":
filter = Expression.NotEqual(left, right);
break;
case "contains":
filter = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] {typeof(string)}),
Expression.Constant(filterObj.Value));
break;
case "in":
var lExp = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组
var methodInfo = typeof(List).GetMethod("Contains",
new Type[] {typeof(string)}); //Contains语句
filter = Expression.Call(lExp, methodInfo, left);
break;
case "not in":
var listExpression = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组
var method = typeof(List).GetMethod("Contains", new Type[] {typeof(string)}); //Contains语句
filter = Expression.Not(Expression.Call(listExpression, method, left));
break;
//交集,使用交集时左值必须时固定的值
case "intersect": //交集
if (property != null)
{
throw new Exception("交集模式下,表达式左边不能为变量,请调整数据规则,如:c=>\"A,B,C\" intersect \"B,D\"");
}
var rightval = filterObj.Value.Split(',').ToList();
var leftval = filterObj.Key.Split(',').ToList();
var val = rightval.Intersect(leftval);
filter = Expression.Constant(val.Count() > 0);
break;
}
return filter;
}
public static Expression> GenerateTypeBody(this ParameterExpression param, Filter filterObj)
{
return (Expression>) (param.GenerateBody(filterObj));
}
///
/// 创建完整的lambda
///
public static LambdaExpression GenerateLambda(this ParameterExpression param, Expression body)
{
//c=>c.XXX=="XXX"
return Expression.Lambda(body, param);
}
public static Expression> GenerateTypeLambda(this ParameterExpression param, Expression body)
{
return (Expression>) (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 IQueryable GenerateFilter(this IQueryable query, string parametername, string filterjson)
{
if (!string.IsNullOrEmpty(filterjson))
{
var filterGroup = JsonHelper.Instance.Deserialize(filterjson);
query = GenerateFilter(query, parametername, filterGroup);
}
return query;
}
public static ISugarQueryable GenerateFilter(this ISugarQueryable query, string parametername, string filterjson)
{
if (!string.IsNullOrEmpty(filterjson))
{
var filterGroup = JsonHelper.Instance.Deserialize(filterjson);
query = GenerateFilter(query, parametername, filterGroup);
}
return query;
}
///
/// 转换FilterGroup为Lambda表达式
///
///
///
///
///
///
public static IQueryable GenerateFilter(this IQueryable query, string parametername,
QueryObject queryObject)
{
var param = CreateLambdaParam(parametername);
Expression result = ConvertGroup(queryObject, param);
query = query.Where(param.GenerateTypeLambda(result));
return query;
}
///
/// 转换FilterGroup为Lambda表达式
///
///
///
///
///
///
public static ISugarQueryable GenerateFilter(this ISugarQueryable query, string parametername,
QueryObject queryObject)
{
var param = CreateLambdaParam(parametername);
Expression result = ConvertGroup(queryObject, param);
query = query.Where(param.GenerateTypeLambda(result));
return query;
}
///
/// 转换filtergroup为表达式
///
///
///
///
///
public static Expression ConvertGroup(QueryObject queryObject, ParameterExpression param)
{
if (queryObject == null) return null;
if (queryObject.Filters.Length == 1 &&(queryObject.Children == null || !queryObject.Children.Any())) //只有一个条件
{
return param.GenerateBody(queryObject.Filters[0]);
}
Expression result = ConvertFilters(queryObject.Filters, param, queryObject.Operation);
Expression gresult = ConvertGroup(queryObject.Children, param, queryObject.Operation);
if (gresult == null) return result;
if (result == null) return gresult;
if (queryObject.Operation == "and")
{
return result.AndAlso(gresult);
}
else //or
{
return Expression.OrElse( result, gresult);
}
}
///
/// 转换FilterGroup[]为表达式,不管FilterGroup里面的Filters
///
///
///
///
///
///
private static Expression ConvertGroup(QueryObject[] queryObjs, ParameterExpression param, string operation)
{
if (queryObjs == null || !queryObjs.Any()) return null;
Expression result = ConvertGroup(queryObjs[0], param);
if (queryObjs.Length == 1) return result;
if (operation == "and")
{
foreach (var filter in queryObjs.Skip(1))
{
result = result.AndAlso(ConvertGroup(filter, param));
}
}
else
{
foreach (var filter in queryObjs.Skip(1))
{
result = Expression.OrElse(result, ConvertGroup(filter, param));
}
}
return result;
}
///
/// 转换Filter数组为表达式
///
///
///
///
///
///
private static Expression ConvertFilters(Filter[] filters, ParameterExpression param, string operation)
{
if (filters == null || !filters.Any())
{
return null;
}
Expression result = param.GenerateBody(filters[0]);
if (filters.Length == 1)
{
return result;
}
if (operation == "and")
{
foreach (var filter in filters.Skip(1))
{
result = result.AndAlso(param.GenerateBody(filter));
}
}
else
{
foreach (var filter in filters.Skip(1))
{
result = Expression.OrElse(result, param.GenerateBody(filter));
}
}
return result;
}
}
}