Handle all possible exceptions using SieveExceptions (#11)

This commit is contained in:
Biarity 2018-02-15 18:53:09 +10:00
parent 6d3fedf9f5
commit 67606e281b
2 changed files with 130 additions and 96 deletions

View File

@ -6,5 +6,12 @@ namespace Sieve.Exceptions
{ {
public class SieveException : Exception public class SieveException : Exception
{ {
public SieveException(string message) : base(message)
{
}
public SieveException(string message, Exception innerException) : base(message, innerException)
{
}
} }
} }

View File

@ -98,90 +98,99 @@ namespace Sieve.Services
IQueryable<TEntity> result, IQueryable<TEntity> result,
object[] dataForCustomMethods = null) object[] dataForCustomMethods = null)
{ {
if (model?.FiltersParsed == null) try
return result;
foreach (var filterTerm in model.FiltersParsed)
{ {
var property = GetSieveProperty<TEntity>(false, true, filterTerm.Name); if (model?.FiltersParsed == null)
return result;
if (property != null) foreach (var filterTerm in model.FiltersParsed)
{ {
var converter = TypeDescriptor.GetConverter(property.PropertyType); var property = GetSieveProperty<TEntity>(false, true, filterTerm.Name);
var parameter = Expression.Parameter(typeof(TEntity), "e");
dynamic filterValue = Expression.Constant( if (property != null)
converter.CanConvertFrom(typeof(string)) ?
converter.ConvertFrom(filterTerm.Value) :
Convert.ChangeType(filterTerm.Value, property.PropertyType));
dynamic propertyValue = Expression.PropertyOrField(parameter, property.Name);
if (filterTerm.OperatorIsCaseInsensitive)
{ {
propertyValue = Expression.Call(propertyValue, var converter = TypeDescriptor.GetConverter(property.PropertyType);
typeof(string).GetMethods() var parameter = Expression.Parameter(typeof(TEntity), "e");
.First(m => m.Name == "ToUpper" && m.GetParameters().Length == 0));
filterValue = Expression.Call(filterValue, dynamic filterValue = Expression.Constant(
typeof(string).GetMethods() converter.CanConvertFrom(typeof(string)) ?
.First(m => m.Name == "ToUpper" && m.GetParameters().Length == 0)); converter.ConvertFrom(filterTerm.Value) :
Convert.ChangeType(filterTerm.Value, property.PropertyType));
dynamic propertyValue = Expression.PropertyOrField(parameter, property.Name);
if (filterTerm.OperatorIsCaseInsensitive)
{
propertyValue = Expression.Call(propertyValue,
typeof(string).GetMethods()
.First(m => m.Name == "ToUpper" && m.GetParameters().Length == 0));
filterValue = Expression.Call(filterValue,
typeof(string).GetMethods()
.First(m => m.Name == "ToUpper" && m.GetParameters().Length == 0));
}
Expression comparison;
switch (filterTerm.OperatorParsed)
{
case FilterOperator.Equals:
comparison = Expression.Equal(propertyValue, filterValue);
break;
case FilterOperator.NotEquals:
comparison = Expression.NotEqual(propertyValue, filterValue);
break;
case FilterOperator.GreaterThan:
comparison = Expression.GreaterThan(propertyValue, filterValue);
break;
case FilterOperator.LessThan:
comparison = Expression.LessThan(propertyValue, filterValue);
break;
case FilterOperator.GreaterThanOrEqualTo:
comparison = Expression.GreaterThanOrEqual(propertyValue, filterValue);
break;
case FilterOperator.LessThanOrEqualTo:
comparison = Expression.LessThanOrEqual(propertyValue, filterValue);
break;
case FilterOperator.Contains:
comparison = Expression.Call(propertyValue,
typeof(string).GetMethods()
.First(m => m.Name == "Contains" && m.GetParameters().Length == 1),
filterValue);
break;
case FilterOperator.StartsWith:
comparison = Expression.Call(propertyValue,
typeof(string).GetMethods()
.First(m => m.Name == "StartsWith" && m.GetParameters().Length == 1),
filterValue); break;
default:
comparison = Expression.Equal(propertyValue, filterValue);
break;
}
result = result.Where(Expression.Lambda<Func<TEntity, bool>>(
comparison,
parameter));
} }
else
Expression comparison;
switch (filterTerm.OperatorParsed)
{ {
case FilterOperator.Equals: result = ApplyCustomMethod(result, filterTerm.Name, _customFilterMethods,
comparison = Expression.Equal(propertyValue, filterValue); new object[] {
break;
case FilterOperator.NotEquals:
comparison = Expression.NotEqual(propertyValue, filterValue);
break;
case FilterOperator.GreaterThan:
comparison = Expression.GreaterThan(propertyValue, filterValue);
break;
case FilterOperator.LessThan:
comparison = Expression.LessThan(propertyValue, filterValue);
break;
case FilterOperator.GreaterThanOrEqualTo:
comparison = Expression.GreaterThanOrEqual(propertyValue, filterValue);
break;
case FilterOperator.LessThanOrEqualTo:
comparison = Expression.LessThanOrEqual(propertyValue, filterValue);
break;
case FilterOperator.Contains:
comparison = Expression.Call(propertyValue,
typeof(string).GetMethods()
.First(m => m.Name == "Contains" && m.GetParameters().Length == 1),
filterValue);
break;
case FilterOperator.StartsWith:
comparison = Expression.Call(propertyValue,
typeof(string).GetMethods()
.First(m => m.Name == "StartsWith" && m.GetParameters().Length == 1),
filterValue); break;
default:
comparison = Expression.Equal(propertyValue, filterValue);
break;
}
result = result.Where(Expression.Lambda<Func<TEntity, bool>>(
comparison,
parameter));
}
else
{
result = ApplyCustomMethod(result, filterTerm.Name, _customFilterMethods,
new object[] {
result, result,
filterTerm.Operator, filterTerm.Operator,
filterTerm.Value filterTerm.Value
}, dataForCustomMethods); }, dataForCustomMethods);
}
} }
}
return result; return result;
}
catch (Exception ex)
{
if (ex is SieveException)
throw;
throw new SieveException(ex.Message, ex);
}
} }
/// <summary> /// <summary>
@ -197,32 +206,41 @@ namespace Sieve.Services
IQueryable<TEntity> result, IQueryable<TEntity> result,
object[] dataForCustomMethods = null) object[] dataForCustomMethods = null)
{ {
if (model?.SortsParsed == null) try
return result;
var useThenBy = false;
foreach (var sortTerm in model.SortsParsed)
{ {
var property = GetSieveProperty<TEntity>(true, false, sortTerm.Name); if (model?.SortsParsed == null)
return result;
if (property != null) var useThenBy = false;
foreach (var sortTerm in model.SortsParsed)
{ {
result = result.OrderByDynamic(property.Name, sortTerm.Descending, useThenBy); var property = GetSieveProperty<TEntity>(true, false, sortTerm.Name);
}
else if (property != null)
{ {
result = ApplyCustomMethod(result, sortTerm.Name, _customSortMethods, result = result.OrderByDynamic(property.Name, sortTerm.Descending, useThenBy);
new object[] }
{ else
{
result = ApplyCustomMethod(result, sortTerm.Name, _customSortMethods,
new object[]
{
result, result,
useThenBy, useThenBy,
sortTerm.Descending sortTerm.Descending
}, dataForCustomMethods); }, dataForCustomMethods);
}
useThenBy = true;
} }
useThenBy = true;
}
return result; return result;
}
catch (Exception ex)
{
if (ex is SieveException)
throw;
throw new SieveException(ex.Message, ex);
}
} }
/// <summary> /// <summary>
@ -237,16 +255,25 @@ namespace Sieve.Services
ISieveModel<IFilterTerm, ISortTerm> model, ISieveModel<IFilterTerm, ISortTerm> model,
IQueryable<TEntity> result) IQueryable<TEntity> result)
{ {
var page = model?.Page ?? 1; try
var pageSize = model?.PageSize ?? _options.Value.DefaultPageSize; {
var maxPageSize = _options.Value.MaxPageSize > 0 ? _options.Value.MaxPageSize : pageSize; var page = model?.Page ?? 1;
var pageSize = model?.PageSize ?? _options.Value.DefaultPageSize;
var maxPageSize = _options.Value.MaxPageSize > 0 ? _options.Value.MaxPageSize : pageSize;
result = result.Skip((page - 1) * pageSize); result = result.Skip((page - 1) * pageSize);
if (pageSize > 0) if (pageSize > 0)
result = result.Take(Math.Min(pageSize, maxPageSize)); result = result.Take(Math.Min(pageSize, maxPageSize));
return result; return result;
}
catch (Exception ex)
{
if (ex is SieveException)
throw;
throw new SieveException(ex.Message, ex);
}
} }