From 204a1b55e24f0cc5519c669d73bfd566da915ac1 Mon Sep 17 00:00:00 2001 From: David Bond Date: Tue, 15 May 2018 00:34:37 +0100 Subject: [PATCH] Fix for Issue #19 --- .editorconfig | 40 +++ Sieve.sln | 7 +- Sieve/Attributes/SieveAttribute.cs | 4 +- Sieve/Exceptions/SieveException.cs | 10 +- .../SieveIncompatibleMethodException.cs | 27 +- .../SieveMethodNotFoundException.cs | 20 +- Sieve/Extensions/OrderByDynamic.cs | 6 +- Sieve/Models/FilterOperator.cs | 8 +- Sieve/Models/FilterTerm.cs | 115 +++----- Sieve/Models/IFilterTerm.cs | 9 +- Sieve/Models/ISieveModel.cs | 11 +- Sieve/Models/ISievePropertyMetadata.cs | 9 +- Sieve/Models/ISortTerm.cs | 9 +- Sieve/Models/SieveModel.cs | 20 +- Sieve/Models/SieveOptions.cs | 9 +- Sieve/Models/SievePropertyMetadata.cs | 9 +- Sieve/Models/SortTerm.cs | 39 +-- Sieve/Services/ISieveCustomFilterMethods.cs | 8 +- Sieve/Services/ISieveCustomSortMethods.cs | 8 +- Sieve/Services/ISieveProcessor.cs | 9 +- Sieve/Services/SieveProcessor.cs | 258 +++++++++--------- Sieve/Services/SievePropertyMapper.cs | 21 +- SieveTests/Controllers/PostsController.cs | 11 +- SieveTests/Entities/ApplicationDbContext.cs | 9 +- SieveTests/Entities/Post.cs | 5 +- SieveTests/Migrations/20180127005347_Init.cs | 10 +- SieveTests/Program.cs | 13 +- .../Services/ApplicationSieveProcessor.cs | 6 +- .../Services/SieveCustomFilterMethods.cs | 14 +- SieveTests/Services/SieveCustomSortMethods.cs | 18 +- SieveTests/Startup.cs | 10 +- SieveUnitTests/Entities/Comment.cs | 10 +- SieveUnitTests/Entities/Post.cs | 5 +- SieveUnitTests/General.cs | 40 ++- SieveUnitTests/Mapper.cs | 10 +- .../Services/ApplicationSieveProcessor.cs | 12 +- .../Services/SieveCustomFilterMethods.cs | 21 +- .../Services/SieveCustomSortMethods.cs | 18 +- .../Services/SieveOptionsAccessor.cs | 15 +- 39 files changed, 379 insertions(+), 504 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..58535d8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,40 @@ +# To learn more about .editorconfig see https://aka.ms/editorconfigdocs +root = true + +# All files +[*] +indent_style = space +trim_trailing_whitespace = true + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 +end_of_line = crlf + +# Xml files +[*.xml] +indent_size = 2 + +# Dotnet code style +[*.{cs,vb}] +# Organize usings +dotnet_sort_system_directives_first = true + +# Avoid this. unless absolutely necessary +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +# Use language keywords instead of BCL types +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Naming conventions +dotnet_naming_style.pascal_case_style.capitalization = pascal_case +# Classes, structs, methods, enums, events, properties, namespaces, delegates must be PascalCase +dotnet_naming_rule.general_naming.severity = suggestion +dotnet_naming_rule.general_naming.symbols = general +dotnet_naming_rule.general_naming.style = pascal_case_style +dotnet_naming_symbols.general.applicable_kinds = class,struct,enum,property,method,event,namespace,delegate +dotnet_naming_symbols.general.applicable_accessibilities = * diff --git a/Sieve.sln b/Sieve.sln index 74844c6..c5d520e 100644 --- a/Sieve.sln +++ b/Sieve.sln @@ -7,7 +7,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sieve", "Sieve\Sieve.csproj EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SieveTests", "SieveTests\SieveTests.csproj", "{8043D264-42A0-4275-97A1-46400C02E37E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SieveUnitTests", "SieveUnitTests\SieveUnitTests.csproj", "{21C3082D-F40E-457F-BE2E-AA099E19E199}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SieveUnitTests", "SieveUnitTests\SieveUnitTests.csproj", "{21C3082D-F40E-457F-BE2E-AA099E19E199}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{904F25A9-5CBD-42AE-8422-ADAB98F4B4B7}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Sieve/Attributes/SieveAttribute.cs b/Sieve/Attributes/SieveAttribute.cs index 47fd398..fd85752 100644 --- a/Sieve/Attributes/SieveAttribute.cs +++ b/Sieve/Attributes/SieveAttribute.cs @@ -1,11 +1,9 @@ using Sieve.Models; using System; -using System.Collections.Generic; -using System.Text; namespace Sieve.Attributes { - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class SieveAttribute : Attribute, ISievePropertyMetadata { /// diff --git a/Sieve/Exceptions/SieveException.cs b/Sieve/Exceptions/SieveException.cs index f657838..8ea5e96 100644 --- a/Sieve/Exceptions/SieveException.cs +++ b/Sieve/Exceptions/SieveException.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Sieve.Exceptions { @@ -13,5 +11,13 @@ namespace Sieve.Exceptions public SieveException(string message, Exception innerException) : base(message, innerException) { } + + public SieveException() + { + } + + protected SieveException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) + { + } } } diff --git a/Sieve/Exceptions/SieveIncompatibleMethodException.cs b/Sieve/Exceptions/SieveIncompatibleMethodException.cs index 8557a4e..890e1b2 100644 --- a/Sieve/Exceptions/SieveIncompatibleMethodException.cs +++ b/Sieve/Exceptions/SieveIncompatibleMethodException.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Sieve.Exceptions { @@ -10,12 +8,11 @@ namespace Sieve.Exceptions public Type ExpectedType { get; protected set; } public Type ActualType { get; protected set; } - public SieveIncompatibleMethodException( - string methodName, + string methodName, Type expectedType, Type actualType, - string message) + string message) : base(message) { MethodName = methodName; @@ -24,16 +21,32 @@ namespace Sieve.Exceptions } public SieveIncompatibleMethodException( - string methodName, + string methodName, Type expectedType, Type actualType, string message, - Exception innerException) + Exception innerException) : base(message, innerException) { MethodName = methodName; ExpectedType = expectedType; ActualType = actualType; } + + public SieveIncompatibleMethodException(string message) : base(message) + { + } + + public SieveIncompatibleMethodException(string message, Exception innerException) : base(message, innerException) + { + } + + public SieveIncompatibleMethodException() + { + } + + protected SieveIncompatibleMethodException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) + { + } } } diff --git a/Sieve/Exceptions/SieveMethodNotFoundException.cs b/Sieve/Exceptions/SieveMethodNotFoundException.cs index 28e2346..c4d5b67 100644 --- a/Sieve/Exceptions/SieveMethodNotFoundException.cs +++ b/Sieve/Exceptions/SieveMethodNotFoundException.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Sieve.Exceptions { @@ -8,7 +6,7 @@ namespace Sieve.Exceptions { public string MethodName { get; protected set; } - public SieveMethodNotFoundException(string methodName, string message) : base (message) + public SieveMethodNotFoundException(string methodName, string message) : base(message) { MethodName = methodName; } @@ -17,5 +15,21 @@ namespace Sieve.Exceptions { MethodName = methodName; } + + public SieveMethodNotFoundException(string message) : base(message) + { + } + + public SieveMethodNotFoundException(string message, Exception innerException) : base(message, innerException) + { + } + + public SieveMethodNotFoundException() + { + } + + protected SieveMethodNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) + { + } } } diff --git a/Sieve/Extensions/OrderByDynamic.cs b/Sieve/Extensions/OrderByDynamic.cs index af39976..414abe7 100644 --- a/Sieve/Extensions/OrderByDynamic.cs +++ b/Sieve/Extensions/OrderByDynamic.cs @@ -1,17 +1,15 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Text; namespace Sieve.Extensions { - public static partial class LinqExtentions + public static partial class LinqExtentions { public static IQueryable OrderByDynamic(this IQueryable source, string orderByProperty, bool desc, bool useThenBy) { - string command = desc ? + string command = desc ? ( useThenBy ? "ThenByDescending" : "OrderByDescending") : ( useThenBy ? "ThenBy" : "OrderBy"); var type = typeof(TEntity); diff --git a/Sieve/Models/FilterOperator.cs b/Sieve/Models/FilterOperator.cs index 0763602..f92c163 100644 --- a/Sieve/Models/FilterOperator.cs +++ b/Sieve/Models/FilterOperator.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Sieve.Models +namespace Sieve.Models { - public enum FilterOperator + public enum FilterOperator { Equals, NotEquals, diff --git a/Sieve/Models/FilterTerm.cs b/Sieve/Models/FilterTerm.cs index 8f647d1..826833e 100644 --- a/Sieve/Models/FilterTerm.cs +++ b/Sieve/Models/FilterTerm.cs @@ -1,14 +1,11 @@ using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Text; +using System.Linq; namespace Sieve.Models { public class FilterTerm : IFilterTerm { - private string _filter; - private string[] operators = new string[] { + private static readonly string[] Operators = new string[] { "==*", "@=*", "_=*", @@ -24,82 +21,50 @@ namespace Sieve.Models public FilterTerm(string filter) { - _filter = filter; + var filterSplits = filter.Split(Operators, StringSplitOptions.RemoveEmptyEntries).Select(t => t.Trim()).ToArray(); + Names = filterSplits[0].Split('|').Select(t => t.Trim()).ToArray(); + Value = filterSplits.Length > 1 ? filterSplits[1] : null; + Operator = Array.Find(Operators, o => filter.Contains(o)) ?? "=="; + OperatorParsed = GetOperatorParsed(Operator); + OperatorIsCaseInsensitive = Operator.Contains("*"); } - public string Name + public string[] Names { get; } + + public FilterOperator OperatorParsed { get; } + + public string Value { get; } + + public string Operator { get; } + + private FilterOperator GetOperatorParsed(string Operator) { - get + switch (Operator.Trim().ToLower()) { - var tokens = _filter.Split(operators, StringSplitOptions.RemoveEmptyEntries); - return tokens.Length > 0 ? tokens[0].Trim() : ""; - + case "==": + case "==*": + return FilterOperator.Equals; + case "!=": + return FilterOperator.NotEquals; + case "<": + return FilterOperator.LessThan; + case ">": + return FilterOperator.GreaterThan; + case ">=": + return FilterOperator.GreaterThanOrEqualTo; + case "<=": + return FilterOperator.LessThanOrEqualTo; + case "@=": + case "@=*": + return FilterOperator.Contains; + case "_=": + case "_=*": + return FilterOperator.StartsWith; + default: + return FilterOperator.Equals; } } - public string Operator - { - get - { - foreach (var op in operators) - { - if (_filter.IndexOf(op) != -1) - { - return op; - } - } - - // Custom operators not supported - // var tokens = _filter.Split(' '); - // return tokens.Length > 2 ? tokens[1] : ""; - return ""; - } - } - - public string Value { - get - { - var tokens = _filter.Split(operators, StringSplitOptions.RemoveEmptyEntries); - return tokens.Length > 1 ? tokens[1].Trim() : null; - } - } - - public FilterOperator OperatorParsed { - get - { - switch (Operator.Trim().ToLower()) - { - case "==": - case "==*": - return FilterOperator.Equals; - case "!=": - return FilterOperator.NotEquals; - case "<": - return FilterOperator.LessThan; - case ">": - return FilterOperator.GreaterThan; - case ">=": - return FilterOperator.GreaterThanOrEqualTo; - case "<=": - return FilterOperator.LessThanOrEqualTo; - case "@=": - case "@=*": - return FilterOperator.Contains; - case "_=": - case "_=*": - return FilterOperator.StartsWith; - default: - return FilterOperator.Equals; - } - } - } - - public bool OperatorIsCaseInsensitive - { - get - { - return Operator.Contains("*"); - } - } + public bool OperatorIsCaseInsensitive { get; } } } \ No newline at end of file diff --git a/Sieve/Models/IFilterTerm.cs b/Sieve/Models/IFilterTerm.cs index d06c657..a7c2baf 100644 --- a/Sieve/Models/IFilterTerm.cs +++ b/Sieve/Models/IFilterTerm.cs @@ -1,13 +1,8 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Text; - -namespace Sieve.Models +namespace Sieve.Models { public interface IFilterTerm { - string Name { get; } + string[] Names { get; } string Operator { get; } bool OperatorIsCaseInsensitive { get; } FilterOperator OperatorParsed { get; } diff --git a/Sieve/Models/ISieveModel.cs b/Sieve/Models/ISieveModel.cs index a9f021f..77e682b 100644 --- a/Sieve/Models/ISieveModel.cs +++ b/Sieve/Models/ISieveModel.cs @@ -1,20 +1,17 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Text; +using System.Collections.Generic; namespace Sieve.Models { - public interface ISieveModel + public interface ISieveModel where TFilterTerm : IFilterTerm where TSortTerm : ISortTerm { string Filters { get; set; } string Sorts { get; set; } - + int? Page { get; set; } - + int? PageSize { get; set; } List FiltersParsed { get; } diff --git a/Sieve/Models/ISievePropertyMetadata.cs b/Sieve/Models/ISievePropertyMetadata.cs index 48f8980..0a36e58 100644 --- a/Sieve/Models/ISievePropertyMetadata.cs +++ b/Sieve/Models/ISievePropertyMetadata.cs @@ -1,11 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; - -namespace Sieve.Models +namespace Sieve.Models { - public interface ISievePropertyMetadata + public interface ISievePropertyMetadata { string Name { get; set; } bool CanFilter { get; set; } diff --git a/Sieve/Models/ISortTerm.cs b/Sieve/Models/ISortTerm.cs index ff38567..c75d30a 100644 --- a/Sieve/Models/ISortTerm.cs +++ b/Sieve/Models/ISortTerm.cs @@ -1,11 +1,6 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Text; - -namespace Sieve.Models +namespace Sieve.Models { - public interface ISortTerm + public interface ISortTerm { bool Descending { get; } string Name { get; } diff --git a/Sieve/Models/SieveModel.cs b/Sieve/Models/SieveModel.cs index 63d5bcb..9e013d1 100644 --- a/Sieve/Models/SieveModel.cs +++ b/Sieve/Models/SieveModel.cs @@ -1,23 +1,20 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Text; namespace Sieve.Models { - public class SieveModel: ISieveModel + public class SieveModel : ISieveModel { public string Filters { get; set; } public string Sorts { get; set; } - [Range(1, Double.MaxValue)] + [Range(1, int.MaxValue)] public int? Page { get; set; } - [Range(1, Double.MaxValue)] + [Range(1, int.MaxValue)] public int? PageSize { get; set; } - public List FiltersParsed { get @@ -30,13 +27,10 @@ namespace Sieve.Models if (filter.StartsWith("(")) { var filterOpAndVal = filter.Substring(filter.LastIndexOf(")") + 1); - var subfilters = filter.Replace(filterOpAndVal, "").Replace("(", "").Replace(")",""); - foreach (var subfilter in subfilters.Split('|')) - { - value.Add(new FilterTerm(subfilter + filterOpAndVal)); - } + var subfilters = filter.Replace(filterOpAndVal, "").Replace("(", "").Replace(")", ""); + value.Add(new FilterTerm(subfilters + filterOpAndVal)); } - else + else { value.Add(new FilterTerm(filter)); } diff --git a/Sieve/Models/SieveOptions.cs b/Sieve/Models/SieveOptions.cs index 4933623..fc866f0 100644 --- a/Sieve/Models/SieveOptions.cs +++ b/Sieve/Models/SieveOptions.cs @@ -1,11 +1,6 @@ -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Text; - -namespace Sieve.Models +namespace Sieve.Models { - public class SieveOptions + public class SieveOptions { public bool CaseSensitive { get; set; } = false; diff --git a/Sieve/Models/SievePropertyMetadata.cs b/Sieve/Models/SievePropertyMetadata.cs index df198b8..ae772b8 100644 --- a/Sieve/Models/SievePropertyMetadata.cs +++ b/Sieve/Models/SievePropertyMetadata.cs @@ -1,11 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; - -namespace Sieve.Models +namespace Sieve.Models { - public class SievePropertyMetadata : ISievePropertyMetadata + public class SievePropertyMetadata : ISievePropertyMetadata { public string Name { get; set; } public bool CanFilter { get; set; } diff --git a/Sieve/Models/SortTerm.cs b/Sieve/Models/SortTerm.cs index bee3342..3b6b10f 100644 --- a/Sieve/Models/SortTerm.cs +++ b/Sieve/Models/SortTerm.cs @@ -1,47 +1,16 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Text; - -namespace Sieve.Models +namespace Sieve.Models { public class SortTerm : ISortTerm { - private string _sort; + private readonly string _sort; public SortTerm(string sort) { _sort = sort; } - public string Name - { - get - { - if (_sort.StartsWith("-")) - { - return _sort.Substring(1); - } - else - { - return _sort; - } - } - } + public string Name => (_sort.StartsWith("-")) ? _sort.Substring(1) : _sort; - public bool Descending - { - get - { - if (_sort.StartsWith("-")) - { - return true; - } - else - { - return false; - } - } - } + public bool Descending => _sort.StartsWith("-"); } } \ No newline at end of file diff --git a/Sieve/Services/ISieveCustomFilterMethods.cs b/Sieve/Services/ISieveCustomFilterMethods.cs index 9d5c2a1..1e3bd42 100644 --- a/Sieve/Services/ISieveCustomFilterMethods.cs +++ b/Sieve/Services/ISieveCustomFilterMethods.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Sieve.Services +namespace Sieve.Services { - public interface ISieveCustomFilterMethods + public interface ISieveCustomFilterMethods { } } diff --git a/Sieve/Services/ISieveCustomSortMethods.cs b/Sieve/Services/ISieveCustomSortMethods.cs index 664f316..cacd9c0 100644 --- a/Sieve/Services/ISieveCustomSortMethods.cs +++ b/Sieve/Services/ISieveCustomSortMethods.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Sieve.Services +namespace Sieve.Services { - public interface ISieveCustomSortMethods + public interface ISieveCustomSortMethods { } } diff --git a/Sieve/Services/ISieveProcessor.cs b/Sieve/Services/ISieveProcessor.cs index 6d02330..df2e812 100644 --- a/Sieve/Services/ISieveProcessor.cs +++ b/Sieve/Services/ISieveProcessor.cs @@ -1,14 +1,13 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Sieve.Models; namespace Sieve.Services { - public interface ISieveProcessor + public interface ISieveProcessor { IQueryable Apply( - ISieveModel model, - IQueryable source, + ISieveModel model, + IQueryable source, object[] dataForCustomMethods = null, bool applyFiltering = true, bool applySorting = true, diff --git a/Sieve/Services/SieveProcessor.cs b/Sieve/Services/SieveProcessor.cs index 7930b2d..264b53c 100644 --- a/Sieve/Services/SieveProcessor.cs +++ b/Sieve/Services/SieveProcessor.cs @@ -1,27 +1,22 @@ -using Microsoft.Extensions.Options; -using Sieve.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Reflection; -using Sieve.Attributes; -using Sieve.Extensions; +using System; using System.ComponentModel; -using System.Collections; +using System.Linq; using System.Linq.Expressions; +using System.Reflection; +using Microsoft.Extensions.Options; +using Sieve.Attributes; using Sieve.Exceptions; +using Sieve.Extensions; +using Sieve.Models; namespace Sieve.Services { public class SieveProcessor : ISieveProcessor { - private IOptions _options; - private ISieveCustomSortMethods _customSortMethods; - private ISieveCustomFilterMethods _customFilterMethods; - private SievePropertyMapper mapper = new SievePropertyMapper(); - + private readonly IOptions _options; + private readonly ISieveCustomSortMethods _customSortMethods; + private readonly ISieveCustomFilterMethods _customFilterMethods; + private readonly SievePropertyMapper mapper = new SievePropertyMapper(); public SieveProcessor(IOptions options, ISieveCustomSortMethods customSortMethods, @@ -67,8 +62,8 @@ namespace Sieve.Services /// Should the data be paginated? Defaults to true. /// Returns a transformed version of `source` public IQueryable Apply( - ISieveModel model, - IQueryable source, + ISieveModel model, + IQueryable source, object[] dataForCustomMethods = null, bool applyFiltering = true, bool applySorting = true, @@ -77,21 +72,29 @@ namespace Sieve.Services var result = source; if (model == null) + { return result; + } try { // Filter if (applyFiltering) + { result = ApplyFiltering(model, result, dataForCustomMethods); + } // Sort if (applySorting) + { result = ApplySorting(model, result, dataForCustomMethods); + } // Paginate if (applyPagination) + { result = ApplyPagination(model, result); + } return result; } @@ -100,7 +103,10 @@ namespace Sieve.Services if (_options.Value.ThrowExceptions) { if (ex is SieveException) + { throw; + } + throw new SieveException(ex.Message, ex); } else @@ -109,105 +115,117 @@ namespace Sieve.Services } } } - + private IQueryable ApplyFiltering( - ISieveModel model, - IQueryable result, + ISieveModel model, + IQueryable result, object[] dataForCustomMethods = null) { if (model?.FiltersParsed == null) - return result; - - foreach (var filterTerm in model.FiltersParsed) { - var property = GetSieveProperty(false, true, filterTerm.Name); - - if (property != null) - { - var converter = TypeDescriptor.GetConverter(property.PropertyType); - var parameter = Expression.Parameter(typeof(TEntity), "e"); - - dynamic filterValue = Expression.Constant( - converter.CanConvertFrom(typeof(string)) ? - converter.ConvertFrom(filterTerm.Value) : - Convert.ChangeType(filterTerm.Value, property.PropertyType)); - - dynamic propertyValue = Expression.PropertyOrField(parameter, property.Name); - - if (filterTerm.OperatorIsCaseInsensitive) - { - propertyValue = Expression.Call(propertyValue, - typeof(string).GetMethods() - .First(m => m.Name == "ToUpper" && m.GetParameters().Length == 0)); - - filterValue = Expression.Call(filterValue, - typeof(string).GetMethods() - .First(m => m.Name == "ToUpper" && m.GetParameters().Length == 0)); - } - - Expression comparison; - - switch (filterTerm.OperatorParsed) - { - case FilterOperator.Equals: - comparison = Expression.Equal(propertyValue, filterValue); - break; - case FilterOperator.NotEquals: - comparison = Expression.NotEqual(propertyValue, filterValue); - break; - case FilterOperator.GreaterThan: - comparison = Expression.GreaterThan(propertyValue, filterValue); - break; - case FilterOperator.LessThan: - comparison = Expression.LessThan(propertyValue, filterValue); - break; - case FilterOperator.GreaterThanOrEqualTo: - comparison = Expression.GreaterThanOrEqual(propertyValue, filterValue); - break; - case FilterOperator.LessThanOrEqualTo: - comparison = Expression.LessThanOrEqual(propertyValue, filterValue); - break; - case FilterOperator.Contains: - comparison = Expression.Call(propertyValue, - typeof(string).GetMethods() - .First(m => m.Name == "Contains" && m.GetParameters().Length == 1), - filterValue); - break; - case FilterOperator.StartsWith: - comparison = Expression.Call(propertyValue, - typeof(string).GetMethods() - .First(m => m.Name == "StartsWith" && m.GetParameters().Length == 1), - filterValue); break; - default: - comparison = Expression.Equal(propertyValue, filterValue); - break; - } - - result = result.Where(Expression.Lambda>( - comparison, - parameter)); - } - else - { - result = ApplyCustomMethod(result, filterTerm.Name, _customFilterMethods, - new object[] { - result, - filterTerm.Operator, - filterTerm.Value - }, dataForCustomMethods); - } + return result; } - return result; + Expression outerExpression = null; + var parameterExpression = Expression.Parameter(typeof(TEntity), "e"); + foreach (var filterTerm in model.FiltersParsed) + { + Expression innerExpression = null; + foreach (var filterTermName in filterTerm.Names) + { + var property = GetSieveProperty(false, true, filterTermName); + if (property != null) + { + var converter = TypeDescriptor.GetConverter(property.PropertyType); + dynamic filterValue = Expression.Constant( + converter.CanConvertFrom(typeof(string)) + ? converter.ConvertFrom(filterTerm.Value) + : Convert.ChangeType(filterTerm.Value, property.PropertyType)); + + dynamic propertyValue = Expression.PropertyOrField(parameterExpression, property.Name); + + if (filterTerm.OperatorIsCaseInsensitive) + { + propertyValue = Expression.Call(propertyValue, + typeof(string).GetMethods() + .First(m => m.Name == "ToUpper" && m.GetParameters().Length == 0)); + + filterValue = Expression.Call(filterValue, + typeof(string).GetMethods() + .First(m => m.Name == "ToUpper" && m.GetParameters().Length == 0)); + } + + if (innerExpression == null) + { + innerExpression = GetExpression(filterTerm, filterValue, propertyValue); + } + else + { + innerExpression = Expression.Or(innerExpression, GetExpression(filterTerm, filterValue, propertyValue)); + } + } + else + { + var parameters = new object[] { + result, + filterTerm.Operator, + filterTerm.Value + }; + result = ApplyCustomMethod(result, filterTermName, _customFilterMethods, parameters, dataForCustomMethods); + } + } + if (outerExpression == null) + { + outerExpression = innerExpression; + continue; + } + outerExpression = Expression.And(outerExpression, innerExpression); + } + return outerExpression == null + ? result + : result.Where(Expression.Lambda>(outerExpression, parameterExpression)); + } + + private static Expression GetExpression(IFilterTerm filterTerm, dynamic filterValue, dynamic propertyValue) + { + switch (filterTerm.OperatorParsed) + { + case FilterOperator.Equals: + return Expression.Equal(propertyValue, filterValue); + case FilterOperator.NotEquals: + return Expression.NotEqual(propertyValue, filterValue); + case FilterOperator.GreaterThan: + return Expression.GreaterThan(propertyValue, filterValue); + case FilterOperator.LessThan: + return Expression.LessThan(propertyValue, filterValue); + case FilterOperator.GreaterThanOrEqualTo: + return Expression.GreaterThanOrEqual(propertyValue, filterValue); + case FilterOperator.LessThanOrEqualTo: + return Expression.LessThanOrEqual(propertyValue, filterValue); + case FilterOperator.Contains: + return Expression.Call(propertyValue, + typeof(string).GetMethods() + .First(m => m.Name == "Contains" && m.GetParameters().Length == 1), + filterValue); + case FilterOperator.StartsWith: + return Expression.Call(propertyValue, + typeof(string).GetMethods() + .First(m => m.Name == "StartsWith" && m.GetParameters().Length == 1), + filterValue); + default: + return Expression.Equal(propertyValue, filterValue); + } } private IQueryable ApplySorting( - ISieveModel model, + ISieveModel model, IQueryable result, object[] dataForCustomMethods = null) { if (model?.SortsParsed == null) + { return result; + } var useThenBy = false; foreach (var sortTerm in model.SortsParsed) @@ -235,7 +253,7 @@ namespace Sieve.Services } private IQueryable ApplyPagination( - ISieveModel model, + ISieveModel model, IQueryable result) { var page = model?.Page ?? 1; @@ -245,20 +263,21 @@ namespace Sieve.Services result = result.Skip((page - 1) * pageSize); if (pageSize > 0) + { result = result.Take(Math.Min(pageSize, maxPageSize)); + } return result; } - protected virtual SievePropertyMapper MapProperties(SievePropertyMapper mapper) { return mapper; } private PropertyInfo GetSieveProperty( - bool canSortRequired, - bool canFilterRequired, + bool canSortRequired, + bool canFilterRequired, string name) { return mapper.FindProperty(canSortRequired, canFilterRequired, name, _options.Value.CaseSensitive) @@ -266,27 +285,21 @@ namespace Sieve.Services } private PropertyInfo FindPropertyBySieveAttribute( - bool canSortRequired, - bool canFilterRequired, + bool canSortRequired, + bool canFilterRequired, string name, - bool isCaseSensitive) - { - return typeof(TEntity).GetProperties().FirstOrDefault(p => + bool isCaseSensitive) => Array.Find(typeof(TEntity).GetProperties(), p => { - if (p.GetCustomAttribute(typeof(SieveAttribute)) is SieveAttribute sieveAttribute) - if ((canSortRequired ? sieveAttribute.CanSort : true) && - (canFilterRequired ? sieveAttribute.CanFilter : true) && - ((sieveAttribute.Name ?? p.Name).Equals(name, - isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))) - return true; - return false; + return p.GetCustomAttribute(typeof(SieveAttribute)) is SieveAttribute sieveAttribute + && (canSortRequired ? sieveAttribute.CanSort : true) + && (canFilterRequired ? sieveAttribute.CanFilter : true) + && ((sieveAttribute.Name ?? p.Name).Equals(name, isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)); }); - } private IQueryable ApplyCustomMethod(IQueryable result, string name, object parent, object[] parameters, object[] optionalParameters = null) { var customMethod = parent?.GetType() - .GetMethod(name, + .GetMethod(name, _options.Value.CaseSensitive ? BindingFlags.Default : BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); if (customMethod != null) @@ -308,7 +321,7 @@ namespace Sieve.Services throw; } } - catch (ArgumentException) // name matched with custom method for a differnt type + catch (ArgumentException) // name matched with custom method for a different type { var expected = typeof(IQueryable); var actual = customMethod.ReturnType; @@ -318,8 +331,7 @@ namespace Sieve.Services } else { - throw new SieveMethodNotFoundException(name, - $"{name} not found."); + throw new SieveMethodNotFoundException(name, $"{name} not found."); } return result; diff --git a/Sieve/Services/SievePropertyMapper.cs b/Sieve/Services/SievePropertyMapper.cs index e77c9aa..3d91c6d 100644 --- a/Sieve/Services/SievePropertyMapper.cs +++ b/Sieve/Services/SievePropertyMapper.cs @@ -4,27 +4,28 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; -using System.Text; namespace Sieve.Services { - public class SievePropertyMapper + public class SievePropertyMapper { - private Dictionary> _map + private readonly Dictionary> _map = new Dictionary>(); public PropertyFluentApi Property(Expression> expression) { if(!_map.ContainsKey(typeof(TEntity))) + { _map.Add(typeof(TEntity), new Dictionary()); + } return new PropertyFluentApi(this, expression); } public class PropertyFluentApi { - private SievePropertyMapper _sievePropertyMapper; - private PropertyInfo _property; + private readonly SievePropertyMapper _sievePropertyMapper; + private readonly PropertyInfo _property; public PropertyFluentApi(SievePropertyMapper sievePropertyMapper, Expression> expression) { @@ -77,7 +78,7 @@ namespace Sieve.Services var ubody = (UnaryExpression)exp.Body; body = ubody.Operand as MemberExpression; } - + return body?.Member as PropertyInfo; } } @@ -92,16 +93,14 @@ namespace Sieve.Services { return _map[typeof(TEntity)] .FirstOrDefault(kv => - kv.Value.Name.Equals(name, isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase) && - (canSortRequired ? kv.Value.CanSort : true) && - (canFilterRequired ? kv.Value.CanFilter : true)).Key; + kv.Value.Name.Equals(name, isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase) + && (canSortRequired ? kv.Value.CanSort : true) + && (canFilterRequired ? kv.Value.CanFilter : true)).Key; } catch (Exception ex) when (ex is KeyNotFoundException || ex is ArgumentNullException) { return null; } - } - } } diff --git a/SieveTests/Controllers/PostsController.cs b/SieveTests/Controllers/PostsController.cs index c936985..30df4db 100644 --- a/SieveTests/Controllers/PostsController.cs +++ b/SieveTests/Controllers/PostsController.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Sieve.Models; @@ -10,11 +7,11 @@ using SieveTests.Entities; namespace SieveTests.Controllers { - [Route("api/[controller]/[action]")] + [Route("api/[controller]/[action]")] public class PostsController : Controller { - private ISieveProcessor _sieveProcessor; - private ApplicationDbContext _dbContext; + private readonly ISieveProcessor _sieveProcessor; + private readonly ApplicationDbContext _dbContext; public PostsController(ISieveProcessor sieveProcessor, ApplicationDbContext dbContext) diff --git a/SieveTests/Entities/ApplicationDbContext.cs b/SieveTests/Entities/ApplicationDbContext.cs index bf592db..9bcd634 100644 --- a/SieveTests/Entities/ApplicationDbContext.cs +++ b/SieveTests/Entities/ApplicationDbContext.cs @@ -1,13 +1,8 @@ -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; namespace SieveTests.Entities { - public class ApplicationDbContext : DbContext + public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions options) : base(options) { } diff --git a/SieveTests/Entities/Post.cs b/SieveTests/Entities/Post.cs index aae37bf..214b66f 100644 --- a/SieveTests/Entities/Post.cs +++ b/SieveTests/Entities/Post.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Sieve.Attributes; namespace SieveTests.Entities { - public class Post + public class Post { public int Id { get; set; } diff --git a/SieveTests/Migrations/20180127005347_Init.cs b/SieveTests/Migrations/20180127005347_Init.cs index 731dd79..9ef971a 100644 --- a/SieveTests/Migrations/20180127005347_Init.cs +++ b/SieveTests/Migrations/20180127005347_Init.cs @@ -1,7 +1,6 @@ -using Microsoft.EntityFrameworkCore.Metadata; +using System; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; -using System; -using System.Collections.Generic; namespace SieveTests.Migrations { @@ -20,10 +19,7 @@ namespace SieveTests.Migrations LikeCount = table.Column(nullable: false), Title = table.Column(nullable: true) }, - constraints: table => - { - table.PrimaryKey("PK_Posts", x => x.Id); - }); + constraints: table => table.PrimaryKey("PK_Posts", x => x.Id)); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/SieveTests/Program.cs b/SieveTests/Program.cs index 8721cf5..255e0c6 100644 --- a/SieveTests/Program.cs +++ b/SieveTests/Program.cs @@ -1,21 +1,14 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore; +using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; namespace SieveTests { - public class Program + public static class Program { public static void Main(string[] args) { var host = BuildWebHost(args); - + host.Run(); } diff --git a/SieveTests/Services/ApplicationSieveProcessor.cs b/SieveTests/Services/ApplicationSieveProcessor.cs index 5fe792d..87e64db 100644 --- a/SieveTests/Services/ApplicationSieveProcessor.cs +++ b/SieveTests/Services/ApplicationSieveProcessor.cs @@ -2,14 +2,10 @@ using Sieve.Models; using Sieve.Services; using SieveTests.Entities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace SieveTests.Services { - public class ApplicationSieveProcessor : SieveProcessor + public class ApplicationSieveProcessor : SieveProcessor { public ApplicationSieveProcessor(IOptions options, ISieveCustomSortMethods customSortMethods, ISieveCustomFilterMethods customFilterMethods) : base(options, customSortMethods, customFilterMethods) { diff --git a/SieveTests/Services/SieveCustomFilterMethods.cs b/SieveTests/Services/SieveCustomFilterMethods.cs index f61d2af..cf620a6 100644 --- a/SieveTests/Services/SieveCustomFilterMethods.cs +++ b/SieveTests/Services/SieveCustomFilterMethods.cs @@ -1,20 +1,12 @@ using Sieve.Services; using SieveTests.Entities; -using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; namespace SieveTests.Services { - public class SieveCustomFilterMethods : ISieveCustomFilterMethods + public class SieveCustomFilterMethods : ISieveCustomFilterMethods { - public IQueryable IsNew(IQueryable source, string op, string value) - { - var result = source.Where(p => p.LikeCount < 100 && - p.CommentCount < 5); - - return result; - } + public IQueryable IsNew(IQueryable source) + => source.Where(p => p.LikeCount < 100 && p.CommentCount < 5); } } diff --git a/SieveTests/Services/SieveCustomSortMethods.cs b/SieveTests/Services/SieveCustomSortMethods.cs index 3f4b811..98f1244 100644 --- a/SieveTests/Services/SieveCustomSortMethods.cs +++ b/SieveTests/Services/SieveCustomSortMethods.cs @@ -1,23 +1,15 @@ -using Sieve.Services; +using System.Linq; +using Sieve.Services; using SieveTests.Entities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace SieveTests.Services { public class SieveCustomSortMethods : ISieveCustomSortMethods { - public IQueryable Popularity(IQueryable source, bool useThenBy, bool desc) - { - var result = useThenBy ? - ((IOrderedQueryable)source).ThenBy(p => p.LikeCount) : - source.OrderBy(p => p.LikeCount) + public IQueryable Popularity(IQueryable source, bool useThenBy) => useThenBy + ? ((IOrderedQueryable)source).ThenBy(p => p.LikeCount) + : source.OrderBy(p => p.LikeCount) .ThenBy(p => p.CommentCount) .ThenBy(p => p.DateCreated); - - return result; - } } } diff --git a/SieveTests/Startup.cs b/SieveTests/Startup.cs index 5d8ceeb..2124d5b 100644 --- a/SieveTests/Startup.cs +++ b/SieveTests/Startup.cs @@ -1,14 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using Sieve.Models; using Sieve.Services; using SieveTests.Entities; @@ -16,7 +10,7 @@ using SieveTests.Services; namespace SieveTests { - public class Startup + public class Startup { public Startup(IConfiguration configuration) { diff --git a/SieveUnitTests/Entities/Comment.cs b/SieveUnitTests/Entities/Comment.cs index b34e945..6aa9acc 100644 --- a/SieveUnitTests/Entities/Comment.cs +++ b/SieveUnitTests/Entities/Comment.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Sieve.Attributes; - -namespace SieveUnitTests.Entities +namespace SieveUnitTests.Entities { - public class Comment + public class Comment { public int Id { get; set; } diff --git a/SieveUnitTests/Entities/Post.cs b/SieveUnitTests/Entities/Post.cs index 4f3c9ab..c4b44d3 100644 --- a/SieveUnitTests/Entities/Post.cs +++ b/SieveUnitTests/Entities/Post.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Sieve.Attributes; namespace SieveUnitTests.Entities { - public class Post + public class Post { public int Id { get; set; } diff --git a/SieveUnitTests/General.cs b/SieveUnitTests/General.cs index ce6ad86..2642bcd 100644 --- a/SieveUnitTests/General.cs +++ b/SieveUnitTests/General.cs @@ -1,20 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Sieve.Exceptions; using Sieve.Models; using Sieve.Services; using SieveUnitTests.Entities; using SieveUnitTests.Services; -using System; -using System.Linq; -using System.Collections.Generic; -using Sieve.Exceptions; namespace SieveUnitTests { [TestClass] public class General { - private SieveProcessor _processor; - private IQueryable _posts; + private readonly SieveProcessor _processor; + private readonly IQueryable _posts; public General() { @@ -43,7 +43,7 @@ namespace SieveUnitTests }, new Post() { Id = 3, - Title = "3", + Title = "D", LikeCount = 3, IsDraft = true }, @@ -86,11 +86,10 @@ namespace SieveUnitTests }; var result = _processor.Apply(model, _posts); - + Assert.IsTrue(result.Count() == 2); } - [TestMethod] public void CanSortBools() { @@ -112,14 +111,12 @@ namespace SieveUnitTests Filters = "LikeCount==50", }; - Console.WriteLine(model.FiltersParsed.First().Value); - Console.WriteLine(model.FiltersParsed.First().Operator); - Console.WriteLine(model.FiltersParsed.First().OperatorParsed); + Console.WriteLine(model.FiltersParsed[0].Value); + Console.WriteLine(model.FiltersParsed[0].Operator); + Console.WriteLine(model.FiltersParsed[0].OperatorParsed); var result = _processor.Apply(model, _posts); - - Assert.AreEqual(result.First().Id, 1); Assert.IsTrue(result.Count() == 1); } @@ -169,15 +166,12 @@ namespace SieveUnitTests }; var result = _processor.Apply(model, _posts); + var entry = result.FirstOrDefault(); + var resultCount = result.Count(); - Assert.AreEqual(result.First().Id, 3); - Assert.IsTrue(result.Count() == 1); + Assert.IsNotNull(entry); + Assert.AreEqual(1, resultCount); + Assert.AreEqual(3, entry.Id); } } -} - -// -//Sorts = "LikeCount", -//Page = 1, -//PageSize = 10 -// \ No newline at end of file +} \ No newline at end of file diff --git a/SieveUnitTests/Mapper.cs b/SieveUnitTests/Mapper.cs index ecb04b5..be32dd1 100644 --- a/SieveUnitTests/Mapper.cs +++ b/SieveUnitTests/Mapper.cs @@ -1,20 +1,18 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Sieve.Models; -using Sieve.Services; using SieveUnitTests.Entities; using SieveUnitTests.Services; -using System; using System.Linq; using System.Collections.Generic; using Sieve.Exceptions; namespace SieveUnitTests { - [TestClass] + [TestClass] public class Mapper { - private ApplicationSieveProcessor _processor; - private IQueryable _posts; + private readonly ApplicationSieveProcessor _processor; + private readonly IQueryable _posts; public Mapper() { @@ -44,7 +42,7 @@ namespace SieveUnitTests }, }.AsQueryable(); } - + [TestMethod] public void MapperWorks() { diff --git a/SieveUnitTests/Services/ApplicationSieveProcessor.cs b/SieveUnitTests/Services/ApplicationSieveProcessor.cs index dd66117..31d1333 100644 --- a/SieveUnitTests/Services/ApplicationSieveProcessor.cs +++ b/SieveUnitTests/Services/ApplicationSieveProcessor.cs @@ -2,19 +2,15 @@ using Sieve.Models; using Sieve.Services; using SieveUnitTests.Entities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace SieveUnitTests.Services { - public class ApplicationSieveProcessor : SieveProcessor + public class ApplicationSieveProcessor : SieveProcessor { public ApplicationSieveProcessor( - IOptions options, - ISieveCustomSortMethods customSortMethods, - ISieveCustomFilterMethods customFilterMethods) + IOptions options, + ISieveCustomSortMethods customSortMethods, + ISieveCustomFilterMethods customFilterMethods) : base(options, customSortMethods, customFilterMethods) { } diff --git a/SieveUnitTests/Services/SieveCustomFilterMethods.cs b/SieveUnitTests/Services/SieveCustomFilterMethods.cs index 0ebce79..39762e3 100644 --- a/SieveUnitTests/Services/SieveCustomFilterMethods.cs +++ b/SieveUnitTests/Services/SieveCustomFilterMethods.cs @@ -1,24 +1,15 @@ -using Sieve.Services; +using System.Linq; +using Sieve.Services; using SieveUnitTests.Entities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace SieveUnitTests.Services { public class SieveCustomFilterMethods : ISieveCustomFilterMethods { - public IQueryable IsNew(IQueryable source, string op, string value) - { - var result = source.Where(p => p.LikeCount < 100); + public IQueryable IsNew(IQueryable source) + => source.Where(p => p.LikeCount < 100); - return result; - } - - public IQueryable TestComment(IQueryable source, string op, string value) - { - return source; - } + public IQueryable TestComment(IQueryable source) + => source; } } diff --git a/SieveUnitTests/Services/SieveCustomSortMethods.cs b/SieveUnitTests/Services/SieveCustomSortMethods.cs index 21825d8..c828125 100644 --- a/SieveUnitTests/Services/SieveCustomSortMethods.cs +++ b/SieveUnitTests/Services/SieveCustomSortMethods.cs @@ -1,23 +1,15 @@ -using Sieve.Services; +using System.Linq; +using Sieve.Services; using SieveUnitTests.Entities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; namespace SieveUnitTests.Services { public class SieveCustomSortMethods : ISieveCustomSortMethods { - public IQueryable Popularity(IQueryable source, bool useThenBy, bool desc) - { - var result = useThenBy ? - ((IOrderedQueryable)source).ThenBy(p => p.LikeCount) : - source.OrderBy(p => p.LikeCount) + public IQueryable Popularity(IQueryable source, bool useThenBy) => useThenBy + ? ((IOrderedQueryable)source).ThenBy(p => p.LikeCount) + : source.OrderBy(p => p.LikeCount) .ThenBy(p => p.CommentCount) .ThenBy(p => p.DateCreated); - - return result; - } } } diff --git a/SieveUnitTests/Services/SieveOptionsAccessor.cs b/SieveUnitTests/Services/SieveOptionsAccessor.cs index 5d02b0d..38e69e6 100644 --- a/SieveUnitTests/Services/SieveOptionsAccessor.cs +++ b/SieveUnitTests/Services/SieveOptionsAccessor.cs @@ -1,26 +1,15 @@ using Microsoft.Extensions.Options; using Sieve.Models; -using System; -using System.Collections.Generic; -using System.Text; namespace SieveUnitTests { public class SieveOptionsAccessor : IOptions { - private SieveOptions _value; - - public SieveOptions Value - { - get - { - return _value; - } - } + public SieveOptions Value { get; } public SieveOptionsAccessor() { - _value = new SieveOptions() + Value = new SieveOptions() { ThrowExceptions = true };