重构 LINQ 表达式以删除重复代码

本文关键字:代码 删除 LINQ 表达式 重构 | 更新日期: 2023-09-27 18:35:59

我有以下一段代码,我尝试重构它以删除重复的代码。但是,每次我尝试重构它时,我都会卡住。有没有人可以帮助我解决这个问题。

    public static IOrderedQueryable<T> ObjectSort<T>(this IQueryable<T> entities, Expression<Func<T, object>> expression, string order = "asc")
    {
        var sortOrder = order == "asc" ? SortOrder.Ascending : SortOrder.Descending;
        return entities.ObjectSort(expression, sortOrder);
    }
    public static IOrderedQueryable<T> ObjectThenBy<T>(this IOrderedQueryable<T> entities, Expression<Func<T, object>> expression, string order = "asc")
    {
        var sortOrder = order == "asc" ? SortOrder.Ascending : SortOrder.Descending;
        return entities.ObjectThenBy(expression, sortOrder);
    }
    public static IOrderedQueryable<T> ObjectSort<T>(this IQueryable<T> entities, Expression<Func<T, object>> expression, SortOrder order = SortOrder.Ascending)
    {
        var unaryExpression = expression.Body as UnaryExpression;
        if (unaryExpression != null)
        {
            var propertyExpression = (MemberExpression)unaryExpression.Operand;
            var parameters = expression.Parameters;
            if (propertyExpression.Type == typeof(DateTime))
            {
                var newExpression = Expression.Lambda<Func<T, DateTime>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(DateTime?))
            {
                var newExpression = Expression.Lambda<Func<T, DateTime?>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(int))
            {
                var newExpression = Expression.Lambda<Func<T, int>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(int?))
            {
                var newExpression = Expression.Lambda<Func<T, int?>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(bool))
            {
                var newExpression = Expression.Lambda<Func<T, bool>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            throw new NotSupportedException("Object type resolution not implemented for this type");
        }
        return order == SortOrder.Ascending ? entities.OrderBy(expression) : entities.OrderByDescending(expression);
    }
    public static IOrderedQueryable<T> ObjectThenBy<T>(this IOrderedQueryable<T> entities, Expression<Func<T, object>> expression, SortOrder order = SortOrder.Ascending)
    {
        var unaryExpression = expression.Body as UnaryExpression;
        if (unaryExpression != null)
        {
            var propertyExpression = (MemberExpression)unaryExpression.Operand;
            var parameters = expression.Parameters;
            if (propertyExpression.Type == typeof(DateTime))
            {
                var newExpression = Expression.Lambda<Func<T, DateTime>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.ThenBy(newExpression) : entities.ThenByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(DateTime?))
            {
                var newExpression = Expression.Lambda<Func<T, DateTime?>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.ThenBy(newExpression) : entities.ThenByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(int))
            {
                var newExpression = Expression.Lambda<Func<T, int>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.ThenBy(newExpression) : entities.ThenByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(int?))
            {
                var newExpression = Expression.Lambda<Func<T, int?>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.ThenBy(newExpression) : entities.ThenByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(bool))
            {
                var newExpression = Expression.Lambda<Func<T, bool>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.ThenBy(newExpression) : entities.ThenByDescending(newExpression);
            }
            throw new NotSupportedException("Object type resolution not implemented for this type");
        }
        return order == SortOrder.Ascending ? entities.ThenBy(expression) : entities.ThenByDescending(expression);
    }

请注意,区别在于Orderby和ThenBy...其余的完全一样。希望有人知道重构它的方法。我试图创建一个 Func 参数来传递 OrderBy 或 ThenBy 方法。然而,我尝试的一切我都被卡住了。

重构 LINQ 表达式以删除重复代码

OrderBy 和 ThenBy

之间的区别在于 OrderBy 期望 IQueryable,ThenBy 期望 IOrderedqueryAble。

现在要使用 OrderBy 或 ThenBy,您需要确定集合是 IQueryable 还是 IOrderedQueryAble。

之后,如果它是IQueryable,则调用OrderBy。如果它是 IOrderedQueryable,则调用 ThenBy (在强制转换为 IOrderedQueryable 之后。

重构的代码片段变为

    public static IOrderedQueryable<T> ObjectSortRefactored<T>(this IQueryable<T> entities, Expression<Func<T, object>> expression, SortOrder order = SortOrder.Ascending)
    {
        var unaryExpression = expression.Body as UnaryExpression;
        if (unaryExpression != null)
        {
            var propertyExpression = (MemberExpression)unaryExpression.Operand;
            var parameters = expression.Parameters;
            if (propertyExpression.Type == typeof(DateTime))
            {
                var newExpression = Expression.Lambda<Func<T, DateTime>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(DateTime?))
            {
                var newExpression = Expression.Lambda<Func<T, DateTime?>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(int))
            {
                var newExpression = Expression.Lambda<Func<T, int>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(int?))
            {
                var newExpression = Expression.Lambda<Func<T, int?>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            if (propertyExpression.Type == typeof(bool))
            {
                var newExpression = Expression.Lambda<Func<T, bool>>(propertyExpression, parameters);
                return order == SortOrder.Ascending ? entities.OrderBy(newExpression) : entities.OrderByDescending(newExpression);
            }
            throw new NotSupportedException("Object type resolution not implemented for this type");
        }
        if(entities.GetType().IsAssignableFrom(typeof(IOrderedQueryable<T>)))
                return order == SortOrder.Ascending ? (entities as IOrderedQueryable<T>).ThenBy(expression) : (entities as IOrderedQueryable<T>).ThenByDescending(expression);
        return order == SortOrder.Ascending ? entities.OrderBy(expression) : entities.OrderByDescending(expression);
    }

不过,我还没有测试上面的代码片段。