// May not handle objects inside of arrays correctly. Only arrays of simple types like strings and numbers public static Expression GetListExpression <T>(Type elementType, Expression member, ListFilterValue filter) { if (filter == null) { return(Expression.Empty()); } var converter = TypeDescriptor.GetConverter(elementType); var elementValue = converter.ConvertFromInvariantString(filter?.Term); var constant = Expression.Constant(elementValue?.ToString().To(elementType)); var method = (typeof(Enumerable)) .GetMethods() .Where(m => m.Name == "Any" && m.GetParameters().Length == 2) .FirstOrDefault() .MakeGenericMethod(elementType); var lambdaParam = Expression.Parameter(elementType, elementType.Name); var lambdaBody = GetStringExpression <T>(elementType, lambdaParam, filter); // If any element of the array matches the filter expression, return that record. return(Expression.Call(method, member, Expression.Lambda(lambdaBody, lambdaParam))); }
public static Expression GetStringExpression <T>(Type propertyType, Expression member, ListFilterValue filter) { // TODO: this can't handle multiple values for single filter. ex: Action: Get|Ignore|Update if (filter == null) { return(Expression.Empty()); } var converter = TypeDescriptor.GetConverter(propertyType); // works for strings and probably any non-complex object var propertyValue = converter.ConvertFromInvariantString(filter?.Term); var constant = Expression.Constant(propertyValue?.ToString().To(propertyType)); var right = Expression.Convert(constant, propertyType); // doesn't yet support the | OR operator switch (filter.Operator) { case ListFilterOperator.Equal: // * operator for start, contains and end if (filter.HasWildcard) { var term = ""; if (filter.WildcardPositions.Count == 2) { term = "Contains"; } else if (filter.WildcardPositions[0] == 0) { term = "EndsWith"; } else if (filter.WildcardPositions[0] > 0) { term = "StartsWith"; } var method = typeof(string).GetMethod(term, new[] { propertyType }); return(Expression.Call(member, method, constant)); } return(Expression.Equal(member, right)); case ListFilterOperator.NotEqual: return(Expression.NotEqual(member, right)); case ListFilterOperator.GreaterThan: return(Expression.GreaterThan(member, right)); case ListFilterOperator.GreaterThanOrEqual: return(Expression.GreaterThanOrEqual(member, right)); case ListFilterOperator.LessThan: return(Expression.LessThan(member, right)); case ListFilterOperator.LessThanOrEqual: return(Expression.LessThanOrEqual(member, right)); default: throw new ArgumentOutOfRangeException(); } }
private static Expression GetEnumExpression <T>(Type propertyType, Expression member, ListFilterValue filter) { // TODO: this can't handle multiple values for single filter. ex: Action: Get|Ignore|Update if (filter == null) { return(Expression.Empty()); } ConstantExpression right = null; if (propertyType.IsEnum) { right = Expression.Constant((int)Enum.Parse(propertyType, filter?.Term).To(propertyType)); } else if (Nullable.GetUnderlyingType(propertyType).IsEnum) { right = Expression.Constant((int)Enum.Parse(propertyType.GenericTypeArguments[0], filter?.Term).To(propertyType)); } //var right = Expression.Constant((int)Enum.Parse(propertyType, filter.Values.FirstOrDefault()?.Term).To(propertyType)); var left = Expression.Convert(member, typeof(int)); switch (filter.Operator) { // doesn't yet support the | OR operator case ListFilterOperator.Equal: return(Expression.Equal(left, right)); case ListFilterOperator.NotEqual: return(Expression.NotEqual(left, right)); default: throw new ArgumentOutOfRangeException(); } }