From fb14eb4ef25623b8b967b074ef8f1f230f7ada8a Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 11 Sep 2020 00:35:21 +0200 Subject: [PATCH] Creating an expression rewritter that work with members --- Kyoo.Common/Controllers/IRepository.cs | 3 +- Kyoo.Common/ExpressionRewrite.cs | 46 +++++++++++++++++++ Kyoo.Common/Models/PeopleRole.cs | 2 + Kyoo.CommonAPI/ApiHelper.cs | 5 +- .../Repositories/PeopleRepository.cs | 20 -------- Kyoo/Models/Resources/CollectionDE.cs | 4 +- 6 files changed, 56 insertions(+), 24 deletions(-) create mode 100644 Kyoo.Common/ExpressionRewrite.cs diff --git a/Kyoo.Common/Controllers/IRepository.cs b/Kyoo.Common/Controllers/IRepository.cs index 62bf0250..47419e88 100644 --- a/Kyoo.Common/Controllers/IRepository.cs +++ b/Kyoo.Common/Controllers/IRepository.cs @@ -30,7 +30,7 @@ namespace Kyoo.Controllers public Sort(Expression> key, bool descendant = false) { - Key = key; + Key = ExpressionRewrite.Rewrite>(key); Descendant = descendant; if (Key == null || @@ -58,6 +58,7 @@ namespace Kyoo.Controllers Key = property.Type.IsValueType ? Expression.Lambda>(Expression.Convert(property, typeof(object)), param) : Expression.Lambda>(property, param); + Key = ExpressionRewrite.Rewrite>(Key); Descendant = order switch { diff --git a/Kyoo.Common/ExpressionRewrite.cs b/Kyoo.Common/ExpressionRewrite.cs new file mode 100644 index 00000000..fadc26b2 --- /dev/null +++ b/Kyoo.Common/ExpressionRewrite.cs @@ -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 Rewrite(Expression expression) where T : Delegate + { + return (Expression)new ExpressionRewrite().Visit(expression); + } + + protected override Expression VisitMember(MemberExpression node) + { + ExpressionRewriteAttribute attr = node.Member.GetCustomAttribute(); + 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; + } + } +} \ No newline at end of file diff --git a/Kyoo.Common/Models/PeopleRole.cs b/Kyoo.Common/Models/PeopleRole.cs index edb760b9..870309a8 100644 --- a/Kyoo.Common/Models/PeopleRole.cs +++ b/Kyoo.Common/Models/PeopleRole.cs @@ -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; diff --git a/Kyoo.CommonAPI/ApiHelper.cs b/Kyoo.CommonAPI/ApiHelper.cs index 7db41430..55b43878 100644 --- a/Kyoo.CommonAPI/ApiHelper.cs +++ b/Kyoo.CommonAPI/ApiHelper.cs @@ -71,8 +71,9 @@ namespace Kyoo.CommonApi else expression = condition; } - - return Expression.Lambda>(expression!, param); + + expression = ExpressionRewrite.Rewrite(expression); + return Expression.Lambda>(expression, param); } private static Expression ContainsResourceExpression(MemberExpression xProperty, string value) diff --git a/Kyoo/Controllers/Repositories/PeopleRepository.cs b/Kyoo/Controllers/Repositories/PeopleRepository.cs index 9ef29490..8bf57f02 100644 --- a/Kyoo/Controllers/Repositories/PeopleRepository.cs +++ b/Kyoo/Controllers/Repositories/PeopleRepository.cs @@ -98,16 +98,6 @@ namespace Kyoo.Controllers Sort 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 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 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 people = await ApplyFilters(_database.PeopleRoles.Where(x => x.Show.Slug == showSlug), id => _database.PeopleRoles.FirstOrDefaultAsync(x => x.ID == id), x => x.People.Name, diff --git a/Kyoo/Models/Resources/CollectionDE.cs b/Kyoo/Models/Resources/CollectionDE.cs index 8235b993..e1368a0c 100644 --- a/Kyoo/Models/Resources/CollectionDE.cs +++ b/Kyoo/Models/Resources/CollectionDE.cs @@ -15,7 +15,9 @@ namespace Kyoo.Models } [JsonIgnore] [NotMergable] public virtual IEnumerable LibraryLinks { get; set; } - /*[ExpressionRewrite(x => x.LibraryLinks, y => y.Genre)]*/ public override IEnumerable Libraries + + [ExpressionRewrite(nameof(LibraryLinks), nameof(GenreLink.Genre))] + public override IEnumerable Libraries { get => LibraryLinks?.Select(x => x.Library); set => LibraryLinks = value?.Select(x => new LibraryLink(x, this));