<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace Riganti.Utils.Infrastructure.Core
{
    /// <summary>
    ///     A base implementation of the query object pattern.
    /// </summary>
    /// <typeparam name="TResult">The type of the result that the query returns.</typeparam>
    public abstract class QueryBase<TResult> : IQuery<TResult>
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="QueryBase{TResult}" /> class.
        /// </summary>
        protected QueryBase()
        {
            SortCriteria = new List<Func<IQueryable<TResult>, IOrderedQueryable<TResult>>>();
        }

        /// <summary>
        ///     Gets or sets a number of rows to be skipped. If this value is null, the paging will be applied.
        /// </summary>
        public int? Skip { get; set; }

        /// <summary>
        ///     Gets or sets the page size. If this value is null, the paging will not be applied.
        /// </summary>
        public int? Take { get; set; }


        /// <summary>
        ///     Gets a list of sort criteria applied on this query.
        /// </summary>
        public IList<Func<IQueryable<TResult>, IOrderedQueryable<TResult>>> SortCriteria { get; }

        /// <summary>
        ///     Adds a specified sort criteria to the query.
        /// </summary>
        public void AddSortCriteria(string fieldName, SortDirection direction = SortDirection.Ascending)
        {
            // create the expression
            var prop = typeof(TResult).GetProperty(fieldName);
            var param = Expression.Parameter(typeof(TResult), "i");
            var expr = Expression.Lambda(Expression.Property(param, prop), param);

            // call the method
            typeof(QueryBase<TResult>).GetMethod(nameof(AddSortCriteriaCore),
                    BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(prop.PropertyType)
                .Invoke(this, new object[] {expr, direction});
        }

        /// <summary>
        ///     Adds a specified sort criteria to the query.
        /// </summary>
        public void AddSortCriteria<TKey>(Expression<Func<TResult, TKey>> field, SortDirection direction)
        {
            AddSortCriteriaCore(field, direction);
        }

        /// <summary>
        ///     Executes the query and returns the results.
        /// </summary>
        public IList<TResult> Execute()
        {
            var query = PreProcessQuery();
            var results = query.ToList();
            PostProcessResults(results);
            return results;
        }

        /// <summary>
        ///     Asynchronously executes the query and returns the results.
        /// </summary>
        public async Task<IList<TResult>> ExecuteAsync()
        {
            return await ExecuteAsync(default(CancellationToken));
        }

        /// <summary>
        ///     Asynchronously executes the query and returns the results.
        /// </summary>
        public async Task<IList<TResult>> ExecuteAsync(CancellationToken cancellationToken)
        {<commit_msg>AddSortCriteria add default value for direction SortDirection.Ascending. Like overload have.<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace Riganti.Utils.Infrastructure.Core
{
    /// <summary>
    ///     A base implementation of the query object pattern.
    /// </summary>
    /// <typeparam name="TResult">The type of the result that the query returns.</typeparam>
    public abstract class QueryBase<TResult> : IQuery<TResult>
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="QueryBase{TResult}" /> class.
        /// </summary>
        protected QueryBase()
        {
            SortCriteria = new List<Func<IQueryable<TResult>, IOrderedQueryable<TResult>>>();
        }

        /// <summary>
        ///     Gets or sets a number of rows to be skipped. If this value is null, the paging will be applied.
        /// </summary>
        public int? Skip { get; set; }

        /// <summary>
        ///     Gets or sets the page size. If this value is null, the paging will not be applied.
        /// </summary>
        public int? Take { get; set; }


        /// <summary>
        ///     Gets a list of sort criteria applied on this query.
        /// </summary>
        public IList<Func<IQueryable<TResult>, IOrderedQueryable<TResult>>> SortCriteria { get; }

        /// <summary>
        ///     Adds a specified sort criteria to the query.
        /// </summary>
        public void AddSortCriteria(string fieldName, SortDirection direction = SortDirection.Ascending)
        {
            // create the expression
            var prop = typeof(TResult).GetProperty(fieldName);
            var param = Expression.Parameter(typeof(TResult), "i");
            var expr = Expression.Lambda(Expression.Property(param, prop), param);

            // call the method
            typeof(QueryBase<TResult>).GetMethod(nameof(AddSortCriteriaCore),
                    BindingFlags.Instance | BindingFlags.NonPublic).MakeGenericMethod(prop.PropertyType)
                .Invoke(this, new object[] {expr, direction});
        }

        /// <summary>
        ///     Adds a specified sort criteria to the query.
        /// </summary>
        public void AddSortCriteria<TKey>(Expression<Func<TResult, TKey>> field, SortDirection direction = SortDirection.Ascending)
        {
            AddSortCriteriaCore(field, direction);
        }

        /// <summary>
        ///     Executes the query and returns the results.
        /// </summary>
        public IList<TResult> Execute()
        {
            var query = PreProcessQuery();
            var results = query.ToList();
            PostProcessResults(results);
            return results;
        }

        /// <summary>
        ///     Asynchronously executes the query and returns the results.
        /// </summary>
        public async Task<IList<TResult>> ExecuteAsync()
        {
            return await ExecuteAsync(default(CancellationToken));
        }

        /// <summary>
        ///     Asynchronously executes the query and returns the results.
        /// </summary>
        public async Task<IList<TResult>> ExecuteAsync(CancellationToken cancellationToken)
        {
{'fraction_non_alphanumeric': 0.11073978429287559, 'fraction_numerical': 0.0, 'mean_word_length': 1.9954504094631482, 'pattern_counts': {'":': 0, '<': 87, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '18035', 'n_tokens_mistral': 1676, 'n_tokens_neox': 1654, 'n_words': 492}