Skip to content

Commit 09b6e5b

Browse files
MilosMilos
Milos
authored and
Milos
committed
Code improvements of "in" filtering
1 parent 88f5cbe commit 09b6e5b

File tree

4 files changed

+39
-27
lines changed

4 files changed

+39
-27
lines changed

src/JsonApiDotNetCore/Extensions/IQueryableExtensions.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,23 @@ namespace JsonApiDotNetCore.Extensions
1212
// ReSharper disable once InconsistentNaming
1313
public static class IQueryableExtensions
1414
{
15+
private static MethodInfo _containsMethod;
16+
private static MethodInfo ContainsMethod
17+
{
18+
get
19+
{
20+
if (_containsMethod == null)
21+
{
22+
_containsMethod = typeof(Enumerable)
23+
.GetMethods(BindingFlags.Static | BindingFlags.Public)
24+
.Where(m => m.Name == nameof(Enumerable.Contains) && m.GetParameters().Count() == 2)
25+
.First();
26+
}
27+
return _containsMethod;
28+
}
29+
}
30+
31+
1532
public static IQueryable<TSource> Sort<TSource>(this IQueryable<TSource> source, List<SortQuery> sortQueries)
1633
{
1734
if (sortQueries == null || sortQueries.Count == 0)
@@ -238,17 +255,7 @@ private static Expression<Func<TSource, bool>> ArrayContainsPredicate<TSource>(s
238255
else
239256
member = Expression.Property(entity, fieldname);
240257

241-
var containsMethods = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(m => m.Name == "Contains");
242-
MethodInfo method = null;
243-
foreach (var m in containsMethods)
244-
{
245-
if (m.GetParameters().Count() == 2)
246-
{
247-
method = m;
248-
break;
249-
}
250-
}
251-
method = method.MakeGenericMethod(member.Type);
258+
var method = ContainsMethod.MakeGenericMethod(member.Type);
252259
var obj = TypeHelper.ConvertListType(propertyValues, member.Type);
253260

254261
var exprContains = Expression.Call(method, new Expression[] { Expression.Constant(obj), member });

src/JsonApiDotNetCore/Internal/TypeHelper.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,15 @@ public static T ConvertType<T>(object value)
6363
/// <param name="values">Collection like ["10","20","30"]</param>
6464
/// <param name="type">Non array type. For e.g. int</param>
6565
/// <returns>Collection of concrete type</returns>
66-
public static object ConvertListType(IEnumerable<string> values, Type type)
66+
public static IList ConvertListType(IEnumerable<string> values, Type type)
6767
{
68-
var convertedArray = new List<object>();
69-
foreach (var value in values)
70-
{
71-
convertedArray.Add(ConvertType(value, type));
72-
}
7368
var listType = typeof(List<>).MakeGenericType(type);
7469
IList list = (IList)Activator.CreateInstance(listType);
75-
foreach (var item in convertedArray)
70+
foreach (var value in values)
7671
{
77-
list.Add(item);
72+
list.Add(ConvertType(value, type));
7873
}
74+
7975
return list;
8076
}
8177
}

src/JsonApiDotNetCore/Services/QueryParser.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ protected virtual List<FilterQuery> ParseFilterQuery(string key, string value)
8585
var propertyName = key.Split(QueryConstants.OPEN_BRACKET, QueryConstants.CLOSE_BRACKET)[1];
8686

8787
// InArray case
88-
var op = GetFilterOperation(value);
89-
if (op == FilterOperations.@in.ToString())
88+
string op = GetFilterOperation(value);
89+
if (string.Equals(op, FilterOperations.@in.ToString(), StringComparison.OrdinalIgnoreCase))
9090
{
9191
(var operation, var filterValue) = ParseFilterOperation(value);
9292
queries.Add(new FilterQuery(propertyName, filterValue, op));
@@ -232,16 +232,17 @@ protected virtual AttrAttribute GetAttribute(string propertyName)
232232

233233
private string GetFilterOperation(string value)
234234
{
235-
var operation = value.Split(QueryConstants.COLON);
235+
var values = value.Split(QueryConstants.COLON);
236236

237-
if (operation.Length == 1)
237+
if (values.Length == 1)
238238
return string.Empty;
239239

240+
var operation = values[0];
240241
// remove prefix from value
241-
if (Enum.TryParse(operation[0], out FilterOperations op) == false)
242+
if (Enum.TryParse(operation, out FilterOperations op) == false)
242243
return string.Empty;
243244

244-
return operation[0];
245+
return operation;
245246
}
246247

247248
private FilterQuery BuildFilterQuery(ReadOnlySpan<char> query, string propertyName)

test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/AttributeFilterTests.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,17 @@ public async Task Can_Filter_On_In_Array_Values()
139139
{
140140
// arrange
141141
var context = _fixture.GetService<AppDbContext>();
142-
var todoItems = _todoItemFaker.Generate(3);
142+
var todoItems = _todoItemFaker.Generate(5);
143143
var guids = new List<Guid>();
144+
var notInGuids = new List<Guid>();
144145
foreach (var item in todoItems)
145146
{
146147
context.TodoItems.Add(item);
147-
guids.Add(item.GuidProperty);
148+
// Exclude 2 items
149+
if (guids.Count < (todoItems.Count() - 2))
150+
guids.Add(item.GuidProperty);
151+
else
152+
notInGuids.Add(item.GuidProperty);
148153
}
149154
context.SaveChanges();
150155

@@ -164,7 +169,10 @@ public async Task Can_Filter_On_In_Array_Values()
164169
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
165170
Assert.Equal(guids.Count(), deserializedTodoItems.Count());
166171
foreach (var item in deserializedTodoItems)
172+
{
167173
Assert.True(guids.Contains(item.GuidProperty));
174+
Assert.False(notInGuids.Contains(item.GuidProperty));
175+
}
168176
}
169177

170178
[Fact]

0 commit comments

Comments
 (0)