62,046
社区成员
发帖
与我相关
我的任务
分享
static void Main(string[] args)
{
Expression greaterThanExpr = Expression.GreaterThan(
Expression.Constant(1),
Expression.Constant((int)Test.NO)
);
Console.WriteLine(greaterThanExpr.ToString());
Console.WriteLine(
Expression.Lambda<Func<bool>>(greaterThanExpr).Compile()());
greaterThanExpr = Expression.GreaterThan(
Expression.Constant(1),
Expression.Constant((int)Test.YES)
);
Console.WriteLine(greaterThanExpr.ToString());
Console.WriteLine(
Expression.Lambda<Func<bool>>(greaterThanExpr).Compile()());
Console.ReadLine();
}
public enum Test
{
NO=0,
YES=1,
}
public class FilterSet<T>
{
public static List<ITransformProvider> TransformProviders { get; set; }
static FilterSet()
{
TransformProviders = new List<ITransformProvider>
{
new DateBlockTransformProvider(),
new GreaterDateTimeTransformProvider(),
new InTransformProvider(),
new LessDateTimeTransformProvider(),
new LikeTransformProvider()
};
}
public IList<FilterItem> Items { get; set; } = new List<FilterItem>();
public Expression<Func<T, bool>> ToExpression()
{
//构建 c=>Body中的c
ParameterExpression param = Expression.Parameter(typeof(T), "c");
if (Items.Count > 0)
{
//构建c=>Body中的Body
var body = GetExpressoinBody(param, Items);
//将二者拼为c=>Body
return Expression.Lambda<Func<T, bool>>(body, param);
}
return Expression.Lambda<Func<T, bool>>(Expression.Constant(true), param);
}
private Expression GetExpressoinBody(ParameterExpression param, IEnumerable<FilterItem> items)
{
//仅支持全And条件
var list = new List<Expression>();
list.Add(GetGroupExpression(param, items, Expression.AndAlso));
return list.Aggregate(Expression.AndAlso);
}
private Expression GetGroupExpression(ParameterExpression param, IEnumerable<FilterItem> items, Func<Expression, Expression, Expression> func)
{
//获取最小的判断表达式
var list = items.Select(item => GetExpression(param, item));
//再以逻辑运算符相连
return list.Aggregate(func);
}
private Expression GetExpression(ParameterExpression param, FilterItem item)
{
//属性表达式
LambdaExpression exp = GetPropertyLambdaExpression(item, param);
//如果有特殊类型处理,则进行处理
foreach (var provider in TransformProviders)
{
if (provider.Match(item, exp.Body.Type))
{
return GetGroupExpression(param, provider.Transform(item, exp.Body.Type), Expression.AndAlso);
}
}
//常量表达式
var constant = ChangeTypeToExpression(item, exp.Body.Type);
//以判断符或方法连接
return ExpressionDict[item.Method](exp.Body, constant);
}
private LambdaExpression GetPropertyLambdaExpression(FilterItem item, ParameterExpression param)
{
//获取每级属性如c.Users.Proiles.UserId
var props = item.FieldName.Split('.');
Expression propertyAccess = param;
var typeOfProp = typeof(T);
int i = 0;
do
{
PropertyInfo property = typeOfProp.GetProperty(props[i]);
if (property == null)
return null;
typeOfProp = property.PropertyType;
propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
i++;
} while (i < props.Length);
return Expression.Lambda(propertyAccess, param);
}
#region ChangeType
/// <summary>
/// 类型转换,支持非空类型与可空类型之间的转换
/// </summary>
/// <param name="value"></param>
/// <param name="conversionType"></param>
/// <returns></returns>
public static object ChangeType(object value, Type conversionType)
{
if (value == null)
return null;
return Convert.ChangeType(value, TypeUtil.GetUnNullableType(conversionType));
}
/// <summary>
/// 转换SearchItem中的Value的类型,为表达式树
/// </summary>
/// <param name="item"></param>
/// <param name="conversionType">目标类型</param>
public static Expression ChangeTypeToExpression(FilterItem item, Type conversionType)
{
if (item.Value == null)
return Expression.Constant(item.Value, conversionType);
#region 数组
if (item.Method == FilterMethod.StandardIn)
{
var arr = (item.Value as Array);
var expList = new List<Expression>();
//确保可用
if (arr != null)
{
for (var i = 0; i < arr.Length; i++)
{
//构造数组的单元Constant
var newValue = ChangeType(arr.GetValue(i), conversionType);
expList.Add(Expression.Constant(newValue, conversionType));
}
}
//构造inType类型的数组表达式树,并为数组赋初值
return Expression.NewArrayInit(conversionType, expList);
}
#endregion
var elementType = TypeUtil.GetUnNullableType(conversionType);
var value = (elementType.IsEnum ? Enum.Parse(conversionType, item.Value.ToString()) : Convert.ChangeType(item.Value, elementType));
//var value = (elementType.IsEnum ? Convert.ChangeType(item.Value, typeof(int)) : Convert.ChangeType(item.Value, elementType));
return Expression.Constant(value, conversionType);
}
#endregion
#region SearchMethod 操作方法
private static readonly Dictionary<FilterMethod, Func<Expression, Expression, Expression>> ExpressionDict =
new Dictionary<FilterMethod, Func<Expression, Expression, Expression>>
{
{ FilterMethod.Eq, (left, right) => { return Expression.Equal(left, right); } },
{ FilterMethod.Gt, (left, right) =>
{
//if (left.Type.IsEnum)
//{
// var methodInfo = left.Type.GetMethod("CompareTo", new Type[]{ left.Type });
// var value = (int)((ConstantExpression)right).Value;
// var eLeft = Expression.Call(left, methodInfo, Expression.Constant(value, typeof(object)) );
// var eRight = Expression.Constant(0, typeof(int));
// return Expression.GreaterThan(eLeft, eRight);
//}
//var lProp = (LambdaExpression)left;
//var rValue = (int)((ConstantExpression)right).Value;
//var eRight = Expression.Constant(rValue);
return Expression.GreaterThan(left, right);
}
},
{ FilterMethod.Ge, (left, right) => { return Expression.GreaterThanOrEqual(left, right); } },
{ FilterMethod.Lt, (left, right) => { return Expression.LessThan(left, right); } },
{ FilterMethod.Le, (left, right) => { return Expression.LessThanOrEqual(left, right); } },
{ FilterMethod.Contains, (left, right) =>
{
if (left.Type != typeof (string))
return null;
return Expression.Call(left, typeof (string).GetMethod("Contains"), right);
}
},
{ FilterMethod.StandardIn, (left, right) =>
{
if (!right.Type.IsArray)
return null;
//调用Enumerable.Contains扩展方法
return Expression.Call(typeof (Enumerable), "Contains", new[] {left.Type}, right, left);
}
},
{ FilterMethod.Nq, (left, right) => { return Expression.NotEqual(left, right); } },
{ FilterMethod.StartsWith, (left, right) =>
{
if (left.Type != typeof (string))
return null;
return Expression.Call(left, typeof (string).GetMethod("StartsWith", new[] {typeof (string)}), right);
}
},
{ FilterMethod.EndsWith, (left, right) =>
{
if (left.Type != typeof (string))
return null;
return Expression.Call(left, typeof (string).GetMethod("EndsWith", new[] {typeof (string)}), right);
}
},
{ FilterMethod.DateTimeLessThanOrEqual, (left, right) => { return Expression.LessThanOrEqual(left, right); } }
};
#endregion
}
代码中标红的语句,会报异常,提示枚举类型没有实现GreaterThan