Solving the afterID lambda

This commit is contained in:
Zoe Roux 2020-07-03 17:10:27 +02:00
parent 1da26b449b
commit 4e9096ae76
4 changed files with 30 additions and 11 deletions

View File

@ -237,6 +237,18 @@ namespace Kyoo
return member.Member.Name; return member.Member.Name;
} }
public static Expression StringCompatibleExpression(Func<Expression, Expression, BinaryExpression> operand,
Expression left,
Expression right)
{
if (left is MemberExpression member && ((PropertyInfo)member.Member).PropertyType == typeof(string))
{
MethodCallExpression call = Expression.Call(typeof(string), "Compare", null, left, right);
return operand(call, Expression.Constant(0));
}
return operand(left, right);
}
public static Expression<Func<T, bool>> ParseWhere<T>(Dictionary<string, string> where) public static Expression<Func<T, bool>> ParseWhere<T>(Dictionary<string, string> where)
{ {
if (where == null || where.Count == 0) if (where == null || where.Count == 0)
@ -259,16 +271,21 @@ namespace Kyoo
if (property == null) if (property == null)
throw new ArgumentException($"No filterable parameter with the name {key}."); throw new ArgumentException($"No filterable parameter with the name {key}.");
MemberExpression propertyExpr = Expression.Property(param, property); MemberExpression propertyExpr = Expression.Property(param, property);
ConstantExpression valueExpr = Expression.Constant(Convert.ChangeType(value, property.PropertyType));
Type propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
object val = string.IsNullOrEmpty(value) || value.Equals("null", StringComparison.OrdinalIgnoreCase)
? null
: Convert.ChangeType(value, propertyType);
ConstantExpression valueExpr = Expression.Constant(val);
Expression condition = operand switch Expression condition = operand switch
{ {
"eq" => Expression.Equal(propertyExpr, valueExpr), "eq" => Expression.Equal(propertyExpr, valueExpr),
"not" => Expression.NotEqual(propertyExpr, valueExpr), "not" => Expression.NotEqual(propertyExpr, valueExpr),
"lt" => Expression.LessThan(propertyExpr, valueExpr), "lt" => StringCompatibleExpression(Expression.LessThan, propertyExpr, valueExpr),
"lte" => Expression.LessThanOrEqual(propertyExpr, valueExpr), "lte" => StringCompatibleExpression(Expression.LessThanOrEqual, propertyExpr, valueExpr),
"gt" => Expression.GreaterThan(propertyExpr, valueExpr), "gt" => StringCompatibleExpression(Expression.GreaterThan, propertyExpr, valueExpr),
"gte" => Expression.GreaterThanOrEqual(propertyExpr, valueExpr), "gte" => StringCompatibleExpression(Expression.GreaterThanOrEqual, propertyExpr, valueExpr),
// TODO Implement the Like expression // TODO Implement the Like expression
"like" => throw new NotImplementedException("Like not implemented yet"), "like" => throw new NotImplementedException("Like not implemented yet"),
_ => throw new ArgumentException($"Invalid operand: {operand}") _ => throw new ArgumentException($"Invalid operand: {operand}")

View File

@ -88,7 +88,8 @@ namespace Kyoo.Controllers
Show after = await Get(page.AfterID); Show after = await Get(page.AfterID);
object afterObj = sortKey.Compile()(after); object afterObj = sortKey.Compile()(after);
query = query.Where(Expression.Lambda<Func<Show, bool>>( query = query.Where(Expression.Lambda<Func<Show, bool>>(
Expression.GreaterThan(sortKey, Expression.Constant(afterObj)) Utility.StringCompatibleExpression(Expression.GreaterThan, sortKey.Body, Expression.Constant(afterObj)),
(ParameterExpression)((MemberExpression)sortKey.Body).Expression
)); ));
} }
query = query.Take(page.Count <= 0 ? 20 : page.Count); query = query.Take(page.Count <= 0 ? 20 : page.Count);

View File

@ -1,11 +1,8 @@
using System; using Kyoo.Models;
using Kyoo.Models;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
using Kyoo.Controllers; using Kyoo.Controllers;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -43,6 +40,10 @@ namespace Kyoo.Api
[FromQuery] int afterID, [FromQuery] int afterID,
[FromQuery] Dictionary<string, string> where) [FromQuery] Dictionary<string, string> where)
{ {
where.Remove("sortBy");
where.Remove("limit");
where.Remove("afterID");
return await _libraryManager.GetShows(Utility.ParseWhere<Show>(where), return await _libraryManager.GetShows(Utility.ParseWhere<Show>(where),
new Sort<Show>(sortBy), new Sort<Show>(sortBy),
new Pagination(limit, afterID)); new Pagination(limit, afterID));