Creating an expression rewritter that work with members

This commit is contained in:
Zoe Roux 2020-09-11 00:35:21 +02:00
parent 8430f0f1d8
commit fb14eb4ef2
6 changed files with 56 additions and 24 deletions

View File

@ -30,7 +30,7 @@ namespace Kyoo.Controllers
public Sort(Expression<Func<T, object>> key, bool descendant = false)
{
Key = key;
Key = ExpressionRewrite.Rewrite<Func<T, object>>(key);
Descendant = descendant;
if (Key == null ||
@ -58,6 +58,7 @@ namespace Kyoo.Controllers
Key = property.Type.IsValueType
? Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param)
: Expression.Lambda<Func<T, object>>(property, param);
Key = ExpressionRewrite.Rewrite<Func<T, object>>(Key);
Descendant = order switch
{

View File

@ -0,0 +1,46 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace Kyoo
{
public class ExpressionRewriteAttribute : Attribute
{
public string Link { get; }
public string Inner { get; }
public ExpressionRewriteAttribute(string link, string inner = null)
{
Link = link;
Inner = inner;
}
}
public class ExpressionRewrite : ExpressionVisitor
{
public static Expression Rewrite(Expression expression)
{
return new ExpressionRewrite().Visit(expression);
}
public static Expression<T> Rewrite<T>(Expression expression) where T : Delegate
{
return (Expression<T>)new ExpressionRewrite().Visit(expression);
}
protected override Expression VisitMember(MemberExpression node)
{
ExpressionRewriteAttribute attr = node.Member.GetCustomAttribute<ExpressionRewriteAttribute>();
if (attr == null)
return base.VisitMember(node);
Expression property = node.Expression;
foreach (string child in attr.Link.Split('.'))
property = Expression.Property(property, child);
if (property is MemberExpression member)
Visit(member.Expression);
return property;
}
}
}

View File

@ -11,12 +11,14 @@ namespace Kyoo.Models
[JsonIgnore] public int PeopleID { get; set; }
[JsonIgnore] public virtual People People { get; set; }
[ExpressionRewrite(nameof(People) + "." + nameof(Models.People.Slug))]
public string Slug
{
get => People.Slug;
set => People.Slug = value;
}
[ExpressionRewrite(nameof(People) + "."+ nameof(Models.People.Name))]
public string Name
{
get => People.Name;

View File

@ -71,8 +71,9 @@ namespace Kyoo.CommonApi
else
expression = condition;
}
return Expression.Lambda<Func<T, bool>>(expression!, param);
expression = ExpressionRewrite.Rewrite(expression);
return Expression.Lambda<Func<T, bool>>(expression, param);
}
private static Expression ContainsResourceExpression(MemberExpression xProperty, string value)

View File

@ -98,16 +98,6 @@ namespace Kyoo.Controllers
Sort<PeopleRole> sort = default,
Pagination limit = default)
{
if (sort.Key?.Body is MemberExpression member)
{
sort.Key = member.Member.Name switch
{
"Name" => x => x.People.Name,
"Slug" => x => x.People.Slug,
_ => sort.Key
};
}
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles.Where(x => x.ShowID == showID),
id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
x => x.People.Name,
@ -124,16 +114,6 @@ namespace Kyoo.Controllers
Sort<PeopleRole> sort = default,
Pagination limit = default)
{
if (sort.Key?.Body is MemberExpression member)
{
sort.Key = member.Member.Name switch
{
"Name" => x => x.People.Name,
"Slug" => x => x.People.Slug,
_ => sort.Key
};
}
ICollection<PeopleRole> people = await ApplyFilters(_database.PeopleRoles.Where(x => x.Show.Slug == showSlug),
id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id),
x => x.People.Name,

View File

@ -15,7 +15,9 @@ namespace Kyoo.Models
}
[JsonIgnore] [NotMergable] public virtual IEnumerable<LibraryLink> LibraryLinks { get; set; }
/*[ExpressionRewrite(x => x.LibraryLinks, y => y.Genre)]*/ public override IEnumerable<Library> Libraries
[ExpressionRewrite(nameof(LibraryLinks), nameof(GenreLink.Genre))]
public override IEnumerable<Library> Libraries
{
get => LibraryLinks?.Select(x => x.Library);
set => LibraryLinks = value?.Select(x => new LibraryLink(x, this));