using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace gehGassi.Common.Data { /// /// Datamanager Erweiterungen /// public static class DataManagerExtensions { #region EF / Syncfusion Extensions public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) { var resultExp = CreateMethodCallExpression(source, "OrderBy", ordering); return source.Provider.CreateQuery(resultExp); } public static IQueryable OrderByDescending(this IQueryable source, string ordering, params object[] values) { var resultExp = CreateMethodCallExpression(source, "OrderByDescending", ordering); return source.Provider.CreateQuery(resultExp); } public static IQueryable ThenBy(this IQueryable source, string ordering, params object[] values) { var resultExp = CreateMethodCallExpression(source, "ThenBy", ordering); return source.Provider.CreateQuery(resultExp); } public static IQueryable ThenByDescending(this IQueryable source, string ordering, params object[] values) { var resultExp = CreateMethodCallExpression(source, "ThenByDescending", ordering); return source.Provider.CreateQuery(resultExp); } private static MethodCallExpression CreateMethodCallExpression(IQueryable source, string methodName, string ordering) { var strings = ordering.Split('.'); var types = new List(); var properties = new List(); var propertyAccesses = new List(); types.Add(typeof(T)); for (int i = 0; i < strings.Length; i++) { if (i != 0) types.Add(properties[i - 1].PropertyType); properties.Add(types[i].GetProperty(strings[i])); } var parameter = Expression.Parameter(types[0], "p"); for (int i = 0; i < properties.Count; i++) { propertyAccesses.Add(i == 0 ? Expression.MakeMemberAccess(parameter, properties[i]) : Expression.MakeMemberAccess(propertyAccesses[i - 1], properties[i])); } var orderByExp = Expression.Lambda(propertyAccesses.Last(), parameter); return Expression.Call(typeof(Queryable), methodName, new Type[] { types.First(), properties.Last().PropertyType }, source.Expression, Expression.Quote(orderByExp)); } #region WHERE /// Generate expression from simple and complex property /// /// /// /// public static Expression GetValueExpression(this ParameterExpression paramExpression, string propertyName, Type sourceType) { Expression expression1 = (Expression)null; if (typeof(ICustomTypeDescriptor).IsAssignableFrom(sourceType)) { Expression.Convert(paramExpression, typeof(ICustomTypeDescriptor)); return (Expression>)((ICustomTypeDescriptor t, object o) => t.GetProperties()[propertyName].GetValue(o)); } string str1 = propertyName; char[] chArray = new char[1] { '.' }; foreach (string str2 in str1.Split(chArray)) { if (expression1 != null) { int result; expression1 = !int.TryParse(str2, out result) ? (Expression)Expression.PropertyOrField(expression1, str2) : (Expression)Expression.ArrayIndex(expression1, (Expression)Expression.Constant((object)result)); } else { Expression expression2 = (Expression)paramExpression; if (paramExpression.Type != sourceType) expression2 = (Expression)Expression.Convert((Expression)paramExpression, sourceType); expression1 = (Expression)Expression.PropertyOrField(expression2, str2); } } return expression1; } public static IQueryable Filter(this IQueryable source, string propertyName, object value, FilterType filterType, bool isCaseSensitive, Type sourceType) { ParameterExpression paramExpression = Expression.Parameter(source.ElementType, sourceType.Name); Expression valueExpression = paramExpression.GetValueExpression(propertyName, sourceType); Type type = valueExpression.Type; //if (Syncfusion.Linq.NullableHelperInternal.IsNullableType(valueExpression.Type)) // type = NullableHelperInternal.GetUnderlyingType(valueExpression.Type); if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { type = Nullable.GetUnderlyingType(type); } if (type == typeof(DateTimeOffset)) { value = DateTimeOffset.Parse(value.ToString()); } else value = Convert.ChangeType((object)value, type); if (filterType == FilterType.Equals || filterType == FilterType.NotEquals || (filterType == FilterType.LessThan || filterType == FilterType.LessThanOrEqual) || (filterType == FilterType.GreaterThan || filterType == FilterType.GreaterThanOrEqual)) { BinaryExpression binaryExpression = (BinaryExpression)null; switch (filterType) { case FilterType.LessThan: binaryExpression = Expression.LessThan(valueExpression, (Expression)Expression.Constant(value, valueExpression.Type)); break; case FilterType.LessThanOrEqual: binaryExpression = Expression.LessThanOrEqual(valueExpression, (Expression)Expression.Constant(value, valueExpression.Type)); break; case FilterType.Equals: binaryExpression = !(type != typeof(string)) ? (!isCaseSensitive ? Expression.Equal((Expression)GetToLowerMethodCallExpression(valueExpression), (Expression)Expression.Constant(value == null ? value : (object)value.ToString().ToLower(), valueExpression.Type)) : Expression.Equal(valueExpression, (Expression)Expression.Constant(value, valueExpression.Type))) : Expression.Equal(valueExpression, (Expression)Expression.Constant(value, valueExpression.Type)); break; case FilterType.NotEquals: binaryExpression = !(type != typeof(string)) ? (!isCaseSensitive ? Expression.NotEqual((Expression)GetToLowerMethodCallExpression(valueExpression), (Expression)Expression.Constant(value == null ? value : (object)value.ToString().ToLower(), valueExpression.Type)) : Expression.NotEqual(valueExpression, (Expression)Expression.Constant(value, valueExpression.Type))) : Expression.NotEqual(valueExpression, (Expression)Expression.Constant(value, valueExpression.Type)); break; case FilterType.GreaterThanOrEqual: binaryExpression = Expression.GreaterThanOrEqual(valueExpression, (Expression)Expression.Constant(value, valueExpression.Type)); break; case FilterType.GreaterThan: binaryExpression = Expression.GreaterThan(valueExpression, (Expression)Expression.Constant(value, valueExpression.Type)); break; } LambdaExpression lambdaExpression = Expression.Lambda((Expression)binaryExpression, new ParameterExpression[1] { paramExpression }); return source.Provider.CreateQuery((Expression)Expression.Call(typeof(Queryable), "Where", new Type[1] { source.ElementType }, new Expression[2] { source.Expression, (Expression)lambdaExpression })); } MethodInfo method = ((IEnumerable)typeof(string).GetMethods()).Where((Func)(m => m.Name == filterType.ToString())).FirstOrDefault(); Expression body; if (isCaseSensitive) body = (Expression)Expression.Call(valueExpression, method, new Expression[1] { (Expression) Expression.Constant(value, typeof (string)) }); else body = (Expression)Expression.Call((Expression)GetToLowerMethodCallExpression(valueExpression), method, new Expression[1] { (Expression) Expression.Constant(value == null ? value : (object) value.ToString().ToLower(), typeof (string)) }); LambdaExpression lambdaExpression1 = Expression.Lambda(body, new ParameterExpression[1] { paramExpression }); return source.Provider.CreateQuery((Expression)Expression.Call(typeof(Queryable), "Where", new Type[1] { source.ElementType }, new Expression[2]{source.Expression,(Expression) lambdaExpression1 })); } public static IQueryable Filter(this IQueryable source, string propertyName, object value, FilterType filterType, bool isCaseSensitive) { Type elementType = source.ElementType; return source.Filter(propertyName, value, filterType, isCaseSensitive, elementType); } private static MethodCallExpression GetToLowerMethodCallExpression(Expression memExp) { MethodInfo method = ((IEnumerable)typeof(string).GetMethods()).FirstOrDefault((Func)(m => m.Name == "ToLower")); return Expression.Call(memExp, method, new Expression[0]); } #endregion #region DataManager public static void SetComplexProperties(this DataManager dm, List properties) { foreach (var complexProperty in properties) { if (dm?.Sorted?.FirstOrDefault(c => c.Name == complexProperty.Original) != null) dm.Sorted.First(c => c.Name == complexProperty.Original).Name = complexProperty.Complex; //if (dm?.Select?.FindIndex(ind => ind.Equals(complexProperty.Original)) > -1) // dm.Select[dm.Select.FindIndex(ind => ind.Equals(complexProperty.Original))] = complexProperty.Complex; if (dm?.Where?.FirstOrDefault(c => c.Field == complexProperty.Original) != null) dm.Where.First(c => c.Field == complexProperty.Original).Field = complexProperty.Complex; if (dm?.Where != null) { foreach (var whereFilter in dm.Where) { SetComplexPropertiesForPredicate(whereFilter, complexProperty); } } } } private static void SetComplexPropertiesForPredicate(WhereFilter whereFilter, ComplexProperty complexProperty) { if (whereFilter.predicates == null) { if (whereFilter.Field == complexProperty.Original) whereFilter.Field = complexProperty.Complex; } else { foreach (var predicate in whereFilter.predicates) { SetComplexPropertiesForPredicate(predicate, complexProperty); } } } public static IQueryable ApplySorting(this DataManager dm, IQueryable source) { if (dm.Sorted != null && dm.Sorted.Count > 0) { var count = 0; foreach (var sort in dm.Sorted) { if (count == 0) source = sort.Direction.ToLower() == "ascending" ? source.OrderBy(sort.Name.ToPascalCase()) : source.OrderByDescending(sort.Name.ToPascalCase()); else source = sort.Direction.ToLower() == "ascending" ? source.ThenBy(sort.Name.ToPascalCase()) : source.ThenByDescending(sort.Name.ToPascalCase()); count += 1; } } return source; } public static IQueryable ApplyFiltering(this DataManager dm, IQueryable source, out int totalCount) { totalCount = 0; if (dm.Where != null) { foreach (var whereFilter in dm.Where) { whereFilter.Field = whereFilter.Field.ToPascalCase(); source = HandlePredicate(whereFilter, source); } } totalCount = source.Count(); return source; } public static IQueryable HandlePredicate(WhereFilter whereFilter, IQueryable source) { if (whereFilter.predicates == null) { var filter = GetFilterOperator(whereFilter.Operator); var filterType = (FilterType)Enum.Parse(typeof(FilterType), filter, true); if (whereFilter.value != null) source = (IQueryable)source.Filter(whereFilter.Field, whereFilter.value, filterType, false); } else { foreach (var predicate in whereFilter.predicates) { source = HandlePredicate(predicate, source); } } return source; } private static string GetFilterOperator(string filter) { if (filter == "equal") filter = "equals"; else if (filter == "notequal") filter = "notequals"; return filter; } public static IQueryable ApplyPaging(this DataManager dm, IQueryable source) { if (dm.Skip != 0) { source = (IQueryable)source.Skip(dm.Skip); } if (dm.Take != 0) { source = (IQueryable)source.Take(dm.Take); } return source; } #endregion #endregion #region Custom #endregion } }