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
}
}