mirror of
https://github.com/Biarity/Sieve.git
synced 2024-11-21 21:12:50 +01:00
Merge branch 'master' of https://github.com/Biarity/Sieve
This commit is contained in:
commit
0dae8c8beb
16
README.md
16
README.md
@ -84,6 +84,15 @@ public class SieveCustomSortMethods : ISieveCustomSortMethods
|
|||||||
|
|
||||||
return result; // Must return modified IQueryable<TEntity>
|
return result; // Must return modified IQueryable<TEntity>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IQueryable<T> Oldest<T>(IQueryable<T> source, bool useThenBy, bool desc) where T : BaseEntity // Generic functions are allowed too
|
||||||
|
{
|
||||||
|
var result = useThenBy ?
|
||||||
|
((IOrderedQueryable<T>)source).ThenByDescending(p => p.DateCreated) :
|
||||||
|
source.OrderByDescending(p => p.DateCreated);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
And `SieveCustomFilterMethods`:
|
And `SieveCustomFilterMethods`:
|
||||||
@ -97,6 +106,12 @@ public class SieveCustomFilterMethods : ISieveCustomFilterMethods
|
|||||||
|
|
||||||
return result; // Must return modified IQueryable<TEntity>
|
return result; // Must return modified IQueryable<TEntity>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IQueryable<T> Latest<T>(IQueryable<T> source, string op, string[] values) where T : BaseEntity // Generic functions are allowed too
|
||||||
|
{
|
||||||
|
var result = source.Where(c => c.DateCreated > DateTimeOffset.UtcNow.AddDays(-14));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -192,6 +207,7 @@ You can replace this DSL with your own (eg. use JSON instead) by implementing an
|
|||||||
| `@=*` | Case-insensitive string Contains |
|
| `@=*` | Case-insensitive string Contains |
|
||||||
| `_=*` | Case-insensitive string Starts with |
|
| `_=*` | Case-insensitive string Starts with |
|
||||||
| `==*` | Case-insensitive string Equals |
|
| `==*` | Case-insensitive string Equals |
|
||||||
|
| `!=*` | Case-insensitive string Not equals |
|
||||||
| `!@=*` | Case-insensitive string does not Contains |
|
| `!@=*` | Case-insensitive string does not Contains |
|
||||||
| `!_=*` | Case-insensitive string does not Starts with |
|
| `!_=*` | Case-insensitive string does not Starts with |
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ namespace Sieve.Models
|
|||||||
private static readonly string[] Operators = new string[] {
|
private static readonly string[] Operators = new string[] {
|
||||||
"!@=*",
|
"!@=*",
|
||||||
"!_=*",
|
"!_=*",
|
||||||
|
"!=*",
|
||||||
"!@=",
|
"!@=",
|
||||||
"!_=",
|
"!_=",
|
||||||
"==*",
|
"==*",
|
||||||
|
@ -187,6 +187,8 @@ namespace Sieve.Services
|
|||||||
propertyValue = Expression.PropertyOrField(propertyValue, part);
|
propertyValue = Expression.PropertyOrField(propertyValue, part);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filterTerm.Values == null) continue;
|
||||||
|
|
||||||
foreach (var filterTermValue in filterTerm.Values)
|
foreach (var filterTermValue in filterTerm.Values)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -335,10 +337,9 @@ namespace Sieve.Services
|
|||||||
var pageSize = model?.PageSize ?? _options.Value.DefaultPageSize;
|
var pageSize = model?.PageSize ?? _options.Value.DefaultPageSize;
|
||||||
var maxPageSize = _options.Value.MaxPageSize > 0 ? _options.Value.MaxPageSize : pageSize;
|
var maxPageSize = _options.Value.MaxPageSize > 0 ? _options.Value.MaxPageSize : pageSize;
|
||||||
|
|
||||||
result = result.Skip((page - 1) * pageSize);
|
|
||||||
|
|
||||||
if (pageSize > 0)
|
if (pageSize > 0)
|
||||||
{
|
{
|
||||||
|
result = result.Skip((page - 1) * pageSize);
|
||||||
result = result.Take(Math.Min(pageSize, maxPageSize));
|
result = result.Take(Math.Min(pageSize, maxPageSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,6 +388,28 @@ namespace Sieve.Services
|
|||||||
_options.Value.CaseSensitive ? BindingFlags.Default : BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance,
|
_options.Value.CaseSensitive ? BindingFlags.Default : BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance,
|
||||||
typeof(IQueryable<TEntity>));
|
typeof(IQueryable<TEntity>));
|
||||||
|
|
||||||
|
|
||||||
|
if (customMethod == null)
|
||||||
|
{
|
||||||
|
// Find generic methods `public IQueryable<T> Filter<T>(IQueryable<T> source, ...)`
|
||||||
|
var genericCustomMethod = parent?.GetType()
|
||||||
|
.GetMethodExt(name,
|
||||||
|
_options.Value.CaseSensitive ? BindingFlags.Default : BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance,
|
||||||
|
typeof(IQueryable<>));
|
||||||
|
|
||||||
|
if (genericCustomMethod != null &&
|
||||||
|
genericCustomMethod.ReturnType.IsGenericType &&
|
||||||
|
genericCustomMethod.ReturnType.GetGenericTypeDefinition() == typeof(IQueryable<>))
|
||||||
|
{
|
||||||
|
var genericBaseType = genericCustomMethod.ReturnType.GenericTypeArguments[0];
|
||||||
|
var constraints = genericBaseType.GetGenericParameterConstraints();
|
||||||
|
if (constraints == null || constraints.Length == 0 || constraints.All((t) => t.IsAssignableFrom(typeof(TEntity))))
|
||||||
|
{
|
||||||
|
customMethod = genericCustomMethod.MakeGenericMethod(typeof(TEntity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (customMethod != null)
|
if (customMethod != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
13
SieveUnitTests/Entities/BaseEntity.cs
Normal file
13
SieveUnitTests/Entities/BaseEntity.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using Sieve.Attributes;
|
||||||
|
|
||||||
|
namespace SieveUnitTests.Entities
|
||||||
|
{
|
||||||
|
public class BaseEntity
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Sieve(CanFilter = true, CanSort = true)]
|
||||||
|
public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
@ -3,13 +3,8 @@ using Sieve.Attributes;
|
|||||||
|
|
||||||
namespace SieveUnitTests.Entities
|
namespace SieveUnitTests.Entities
|
||||||
{
|
{
|
||||||
public class Comment
|
public class Comment : BaseEntity
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
[Sieve(CanFilter = true, CanSort = true)]
|
|
||||||
public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow;
|
|
||||||
|
|
||||||
[Sieve(CanFilter = true)]
|
[Sieve(CanFilter = true)]
|
||||||
public string Text { get; set; }
|
public string Text { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,8 @@ using Sieve.Attributes;
|
|||||||
|
|
||||||
namespace SieveUnitTests.Entities
|
namespace SieveUnitTests.Entities
|
||||||
{
|
{
|
||||||
public class Post
|
public class Post : BaseEntity
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
[Sieve(CanFilter = true, CanSort = true)]
|
[Sieve(CanFilter = true, CanSort = true)]
|
||||||
public string Title { get; set; } = Guid.NewGuid().ToString().Replace("-", string.Empty).Substring(0, 8);
|
public string Title { get; set; } = Guid.NewGuid().ToString().Replace("-", string.Empty).Substring(0, 8);
|
||||||
@ -16,9 +15,6 @@ namespace SieveUnitTests.Entities
|
|||||||
[Sieve(CanFilter = true, CanSort = true)]
|
[Sieve(CanFilter = true, CanSort = true)]
|
||||||
public int CommentCount { get; set; } = new Random().Next(0, 1000);
|
public int CommentCount { get; set; } = new Random().Next(0, 1000);
|
||||||
|
|
||||||
[Sieve(CanFilter = true, CanSort = true)]
|
|
||||||
public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow;
|
|
||||||
|
|
||||||
[Sieve(CanFilter = true, CanSort = true)]
|
[Sieve(CanFilter = true, CanSort = true)]
|
||||||
public int? CategoryId { get; set; } = new Random().Next(0, 4);
|
public int? CategoryId { get; set; } = new Random().Next(0, 4);
|
||||||
|
|
||||||
|
@ -96,6 +96,20 @@ namespace SieveUnitTests
|
|||||||
Assert.IsTrue(result.Count() == 1);
|
Assert.IsTrue(result.Count() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void NotEqualsCanBeCaseInsensitive()
|
||||||
|
{
|
||||||
|
var model = new SieveModel()
|
||||||
|
{
|
||||||
|
Filters = "Title!=*a"
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _processor.Apply(model, _posts);
|
||||||
|
|
||||||
|
Assert.AreEqual(result.First().Id, 1);
|
||||||
|
Assert.IsTrue(result.Count() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void ContainsIsCaseSensitive()
|
public void ContainsIsCaseSensitive()
|
||||||
{
|
{
|
||||||
@ -193,6 +207,20 @@ namespace SieveUnitTests
|
|||||||
Assert.IsTrue(result.Count() == 3);
|
Assert.IsTrue(result.Count() == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CustomGenericFiltersWork()
|
||||||
|
{
|
||||||
|
var model = new SieveModel()
|
||||||
|
{
|
||||||
|
Filters = "Latest",
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _processor.Apply(model, _comments);
|
||||||
|
|
||||||
|
Assert.IsFalse(result.Any(p => p.Id == 0));
|
||||||
|
Assert.IsTrue(result.Count() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void CustomFiltersWithOperatorsWork()
|
public void CustomFiltersWithOperatorsWork()
|
||||||
{
|
{
|
||||||
@ -272,6 +300,19 @@ namespace SieveUnitTests
|
|||||||
Assert.IsFalse(result.First().Id == 0);
|
Assert.IsFalse(result.First().Id == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void CustomGenericSortsWork()
|
||||||
|
{
|
||||||
|
var model = new SieveModel()
|
||||||
|
{
|
||||||
|
Sorts = "Oldest",
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _processor.Apply(model, _posts);
|
||||||
|
|
||||||
|
Assert.IsTrue(result.Last().Id == 0);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void MethodNotFoundExceptionWork()
|
public void MethodNotFoundExceptionWork()
|
||||||
{
|
{
|
||||||
|
@ -32,5 +32,11 @@ namespace SieveUnitTests.Services
|
|||||||
{
|
{
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IQueryable<T> Latest<T>(IQueryable<T> source, string op, string[] values) where T : BaseEntity
|
||||||
|
{
|
||||||
|
var result = source.Where(c => c.DateCreated > DateTimeOffset.UtcNow.AddDays(-14));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,5 +16,14 @@ namespace SieveUnitTests.Services
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IQueryable<T> Oldest<T>(IQueryable<T> source, bool useThenBy, bool desc) where T : BaseEntity
|
||||||
|
{
|
||||||
|
var result = useThenBy ?
|
||||||
|
((IOrderedQueryable<T>)source).ThenByDescending(p => p.DateCreated) :
|
||||||
|
source.OrderByDescending(p => p.DateCreated);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user