< Summary

Information
Class: Fluorite.Strainer.Services.Sorting.SortExpressionProvider
Assembly: Fluorite.Strainer
File(s): /builds/fluorite/strainer/src/Strainer/Services/Sorting/SortExpressionProvider.cs
Line coverage
100%
Covered lines: 44
Uncovered lines: 0
Coverable lines: 44
Total lines: 120
Line coverage: 100%
Branch coverage
100%
Covered branches: 14
Total branches: 14
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
GetDefaultExpression()100%66100%
GetExpression(...)100%44100%
GetExpressions(...)100%44100%

File(s)

/builds/fluorite/strainer/src/Strainer/Services/Sorting/SortExpressionProvider.cs

#LineLine coverage
 1using Fluorite.Strainer.Models.Metadata;
 2using Fluorite.Strainer.Models.Sorting;
 3using Fluorite.Strainer.Models.Sorting.Terms;
 4using Fluorite.Strainer.Services.Metadata;
 5using System.Linq.Expressions;
 6
 7namespace Fluorite.Strainer.Services.Sorting;
 8
 9/// <summary>
 10/// Provides means of tranlating <see cref="ISortTerm"/> into
 11/// <see cref="Expression{TDelegate}"/> of <see cref="Func{T, TResult}"/>.
 12/// <para/>
 13/// In other words - provides list of expressions which later can be used
 14/// as arguments for ordering <see cref="IQueryable{T}"/>.
 15/// </summary>
 16public class SortExpressionProvider : ISortExpressionProvider
 17{
 18    private readonly IMetadataFacade _metadataProvidersFacade;
 19    private readonly IStrainerOptionsProvider _strainerOptionsProvider;
 20
 21    /// <summary>
 22    /// Initializes a new instance of the <see cref="SortExpressionProvider"/> class.
 23    /// </summary>
 724    public SortExpressionProvider(
 725        IMetadataFacade metadataProvidersFacade,
 726        IStrainerOptionsProvider strainerOptionsProvider)
 27    {
 728        _metadataProvidersFacade = Guard.Against.Null(metadataProvidersFacade);
 729        _strainerOptionsProvider = Guard.Against.Null(strainerOptionsProvider);
 730    }
 31
 32    /// <inheritdoc/>
 33    public ISortExpression<TEntity>? GetDefaultExpression<TEntity>()
 34    {
 335        var propertyMetadata = _metadataProvidersFacade.GetDefaultMetadata<TEntity>();
 336        if (propertyMetadata is null)
 37        {
 138            return null;
 39        }
 40
 241        var name = propertyMetadata.DisplayName ?? propertyMetadata.Name;
 242        var defaultSortingWay = propertyMetadata.DefaultSortingWay
 243            ?? _strainerOptionsProvider.GetStrainerOptions().DefaultSortingWay;
 244        var isDescending = defaultSortingWay == SortingWay.Descending;
 245        var sortTerm = new SortTerm(name)
 246        {
 247            IsDescending = isDescending,
 248        };
 49
 250        return GetExpression<TEntity>(propertyMetadata, sortTerm, isSubsequent: false);
 51    }
 52
 53    /// <inheritdoc/>
 54    /// <exception cref="ArgumentNullException">
 55    /// <paramref name="propertyMetadata"/> is <see langword="null"/>.
 56    /// <paramref name="sortTerm"/> is <see langword="null"/>.
 57    /// </exception>
 58    public ISortExpression<TEntity> GetExpression<TEntity>(
 59        IPropertyMetadata propertyMetadata,
 60        ISortTerm sortTerm,
 61        bool isSubsequent)
 62    {
 663        Guard.Against.Null(propertyMetadata);
 664        Guard.Against.Null(sortTerm);
 65
 666        var parameter = Expression.Parameter(typeof(TEntity), "p");
 667        Expression propertyValue = parameter;
 68
 669        if (propertyMetadata.Name.Contains("."))
 70        {
 171            var parts = propertyMetadata.Name.Split('.');
 72
 473            for (var i = 0; i < parts.Length - 1; i++)
 74            {
 175                propertyValue = Expression.PropertyOrField(propertyValue, parts[i]);
 76            }
 77        }
 78
 679        var propertyAccess = Expression.MakeMemberAccess(propertyValue, propertyMetadata.PropertyInfo!);
 680        var conversion = Expression.Convert(propertyAccess, typeof(object));
 681        var orderExpression = Expression.Lambda<Func<TEntity, object>>(conversion, parameter);
 82
 683        return new SortExpression<TEntity>(orderExpression)
 684        {
 685            IsDefault = propertyMetadata.IsDefaultSorting,
 686            IsDescending = sortTerm.IsDescending,
 687            IsSubsequent = isSubsequent,
 688        };
 89    }
 90
 91    /// <inheritdoc/>
 92    /// <exception cref="ArgumentNullException">
 93    /// <paramref name="sortTerms"/> is <see langword="null"/>.
 94    /// </exception>
 95    public IReadOnlyList<ISortExpression<TEntity>> GetExpressions<TEntity>(
 96        IEnumerable<KeyValuePair<IPropertyMetadata, ISortTerm>> sortTerms)
 97    {
 398        Guard.Against.Null(sortTerms);
 99
 3100        var expressions = new List<ISortExpression<TEntity>>();
 3101        var isSubqequent = false;
 102
 14103        foreach (var pair in sortTerms)
 104        {
 4105            var sortExpression = GetExpression<TEntity>(pair.Key, pair.Value, isSubqequent);
 4106            if (sortExpression != null)
 107            {
 4108                expressions.Add(sortExpression);
 109            }
 110            else
 111            {
 112                continue;
 113            }
 114
 4115            isSubqequent = true;
 116        }
 117
 3118        return expressions.AsReadOnly();
 119    }
 120}