private static IEnumerable <EntityPropertyFilter> GenerateEntityPropertyFilters(ICollection <PropertyInfo> propertyInfos, string parentPropertyName) { var result = new List <EntityPropertyFilter>(); var domainEntitiesNameSpace = typeof(Entity <>).Namespace; var nativeProperties = propertyInfos.Where(p => p.PropertyType.Namespace != domainEntitiesNameSpace && !p.Name.EndsWith("Id")); foreach (var propertyInfo in nativeProperties) { var propertyName = !string.IsNullOrEmpty(parentPropertyName) ? $"{parentPropertyName}.{propertyInfo.Name}" : propertyInfo.Name; var entityPropertyFilter = new EntityPropertyFilter { Name = propertyName, ValueType = propertyInfo.PropertyType }; result.Add(entityPropertyFilter); } var entityProperties = propertyInfos.Where(propertyInfo => propertyInfo.PropertyType.Namespace == domainEntitiesNameSpace && !propertyInfo.Name.EndsWith("Id")); foreach (var propertyInfo in entityProperties) { var nextParentPropertyName = !string.IsNullOrEmpty(parentPropertyName) ? $"{parentPropertyName}.{propertyInfo.Name}" : propertyInfo.Name; var nextPropertyInfos = propertyInfo.PropertyType.GetProperties(); var nextResult = GenerateEntityPropertyFilters(nextPropertyInfos, nextParentPropertyName); result.AddRange(nextResult); } return(result); }
private static Expression <Func <TEntity, bool> > Express(EntityPropertyFilter entityPropertyFilter) { var entityParameter = Expression.Parameter(typeof(TEntity), typeof(TEntity).Name.ToCamelCase()); var entityPropertyExpression = NestedExpressionProperty(entityParameter, entityPropertyFilter.Name); if (entityPropertyFilter.Values == null) { var message = $"Values property cannot be null for PropertyFilter with Id: '{entityPropertyFilter.Id}'"; throw new ArgumentException(message); } if (!entityPropertyFilter.Values.Any()) { var message = $"Values property cannot be empty for PropertyFilter with Id: '{entityPropertyFilter.Id}'"; throw new ArgumentException(message); } ConstantExpression valuesExpression; ConstantExpression firstValueExpression; ConstantExpression secondValueExpression; if (entityPropertyFilter.ValueType == typeof(int)) { var values = entityPropertyFilter.Values.ConvertAllToInt().ToArray(); valuesExpression = Expression.Constant(values, values.GetType()); firstValueExpression = Expression.Constant(values.First(), entityPropertyFilter.ValueType); secondValueExpression = (values.Length > 1) ? Expression.Constant(values.Skip(1).First(), entityPropertyFilter.ValueType) : null; } else if (entityPropertyFilter.ValueType == typeof(DateTime)) { var values = entityPropertyFilter.Values.ConvertAllToDateTime().ToArray(); valuesExpression = Expression.Constant(values, values.GetType()); firstValueExpression = Expression.Constant(values.First(), entityPropertyFilter.ValueType); secondValueExpression = (values.Length > 1) ? Expression.Constant(values.Skip(1).First(), entityPropertyFilter.ValueType) : null; } else if (entityPropertyFilter.ValueType == typeof(Double)) { var values = entityPropertyFilter.Values.ConvertAllToDouble().ToArray(); valuesExpression = Expression.Constant(values, values.GetType()); firstValueExpression = Expression.Constant(values.First(), entityPropertyFilter.ValueType); secondValueExpression = (values.Length > 1) ? Expression.Constant(values.Skip(1).First(), entityPropertyFilter.ValueType) : null; } else if (entityPropertyFilter.ValueType == typeof(string)) { valuesExpression = Expression.Constant(entityPropertyFilter.Values, entityPropertyFilter.Values.GetType()); firstValueExpression = Expression.Constant(entityPropertyFilter.Values.First(), entityPropertyFilter.ValueType); secondValueExpression = (entityPropertyFilter.Values.Count > 1) ? Expression.Constant(entityPropertyFilter.Values.Skip(1).First(), entityPropertyFilter.ValueType) : null; } else { var message = $"An implementation for ValueType of '{entityPropertyFilter.ValueType}' has not been found for PropertyFilter with Id: '{entityPropertyFilter.Id}'."; throw new NotImplementedException(message); } var stringStartsWithMethodInfo = typeof(string).GetMethod("StartsWith", new[] { typeof(string) }); var stringContainsMethodInfo = typeof(string).GetMethod("Contains", new[] { typeof(string) }); var stringEndsWithMethodInfo = typeof(string).GetMethod("EndsWith", new[] { typeof(string) }); var enumerableContainsMethodInfo = typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static) .First(m => m.Name == "Contains" && m.GetParameters().Length == 2) .MakeGenericMethod(entityPropertyFilter.ValueType); var noneExpression = Expression.Constant(true); var defaultExpression = Expression.Constant(false); var arguments = new Expression[] { firstValueExpression }; var startsWithExpression = entityPropertyFilter.ValueType == typeof(string) ? Expression.Call(entityPropertyExpression, stringStartsWithMethodInfo, arguments) : null; var containsExpression = entityPropertyFilter.ValueType == typeof(string) ? Expression.Call(entityPropertyExpression, stringContainsMethodInfo, arguments) : null; var endsWithExpression = entityPropertyFilter.ValueType == typeof(string) ? Expression.Call(entityPropertyExpression, stringEndsWithMethodInfo, arguments) : null; var inExpression = Expression.Call(enumerableContainsMethodInfo, new Expression[] { valuesExpression, entityPropertyExpression }); var equalsExpression = Expression.Equal(entityPropertyExpression, firstValueExpression); BinaryExpression greaterThanExpression = null; BinaryExpression lessThanExpression = null; BinaryExpression betweenExpression = null; if (entityPropertyFilter.ValueType != typeof(string)) { greaterThanExpression = Expression.GreaterThan(entityPropertyExpression, firstValueExpression); lessThanExpression = Expression.LessThan(entityPropertyExpression, firstValueExpression); if (secondValueExpression != null) { betweenExpression = Expression.And(greaterThanExpression, Expression.LessThan(entityPropertyExpression, secondValueExpression)); } } switch (entityPropertyFilter.ComparisonOperator) { case ComparisonOperator.None: return(Expression.Lambda <Func <TEntity, bool> >(noneExpression, entityParameter)); case ComparisonOperator.In: return(Expression.Lambda <Func <TEntity, bool> >(inExpression, entityParameter)); case ComparisonOperator.NotIn: return(Expression.Lambda <Func <TEntity, bool> >(Expression.Not(inExpression), entityParameter)); case ComparisonOperator.Between: return(Expression.Lambda <Func <TEntity, bool> >(betweenExpression, entityParameter)); case ComparisonOperator.StartsWith: return(Expression.Lambda <Func <TEntity, bool> >(startsWithExpression, entityParameter)); case ComparisonOperator.Contains: return(Expression.Lambda <Func <TEntity, bool> >(containsExpression, entityParameter)); case ComparisonOperator.EndsWith: return(Expression.Lambda <Func <TEntity, bool> >(endsWithExpression, entityParameter)); case ComparisonOperator.Equals: return(Expression.Lambda <Func <TEntity, bool> >(equalsExpression, entityParameter)); case ComparisonOperator.NotEquals: return(Expression.Lambda <Func <TEntity, bool> >(Expression.Not(equalsExpression), entityParameter)); case ComparisonOperator.GreaterThan: return(Expression.Lambda <Func <TEntity, bool> >(greaterThanExpression, entityParameter)); case ComparisonOperator.LessThan: return(Expression.Lambda <Func <TEntity, bool> >(lessThanExpression, entityParameter)); default: return(Expression.Lambda <Func <TEntity, bool> >(defaultExpression, entityParameter)); } }
public EntityPropertySelector(EntityPropertyFilter filter) { this.filter = filter; }
public EntityPropertySelector(EntityPropertyFilterConfig parent, string key, Func <HttpRequestMessage, bool> filterExpression) { this.filter = new EntityPropertyFilter(typeof(TEntityType), key, filterExpression); parent.Filters.Add(this.filter); }