С# Linq OrderBy Reflection с . строка с разделителями

Мне нужно использовать строку с разделителями в порядке. ЭГ "Товар.Справочник".

Кажется, у меня проблемы, так как результат упорядочивается так же, как и до вызова метода.

Например, у меня есть этот тест xUnit, который показывает мою проблему. Утверждения показывают, что порядок остается прежним.

Обновлено: чтобы было ясно, я тестирую не Order by, а метод PathToProperty. Этот тест предназначен только для демонстрационных целей.

Как видно из теста, я использую метод отражения private static object PathToProperty(object t, string path) Итак, я предполагаю, что делаю что-то не так?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Xunit;

namespace Pip17PFinanceApi.Tests.Workers
{
    public class InputViewModel
    {
        public List<OrderViewModel> OrderViewModels { get; set; }
    }

    public class OrderViewModel
    {
        public Product Product { get; set; }
        public decimal Price { get; set; }
    }

    public class Product
    {
        public string Description { get; set; }
        public string Reference { get; set; }
    }

    public class OrderByWithReflection
    {
        [Fact]
        public void OrderByTest()
        {
            //Arrrange
            var model = new InputViewModel
            {
                OrderViewModels = new List<OrderViewModel>
                    {
                        new OrderViewModel{
                            Product = new Product
                            {
                                Reference = "02"
                            }
                        },
                        new OrderViewModel{
                            Product = new Product
                            {
                                Reference = "03"
                            }
                        },
                        new OrderViewModel{
                            Product = new Product
                            {
                                Reference = "01"
                            }
                        },
                        new OrderViewModel{
                            Product = new Product
                            {
                                Reference = "04"
                            }
                        },
                    }
            };

            //Act
            var query = model.OrderViewModels.OrderBy(t => PathToProperty(t, "Product.Reference"));
            var result = query.ToList();

            //Assert
            Assert.Equal("01", result[0].Product.Reference);
            Assert.Equal("02", result[1].Product.Reference);
            Assert.Equal("03", result[2].Product.Reference);
            Assert.Equal("04", result[3].Product.Reference);
        }

        private static object PathToProperty(object t, string path)
        {
            Type currentType = t.GetType();
            foreach (string propertyName in path.Split('.'))
            {
                PropertyInfo property = currentType.GetProperty(propertyName);
                t = property;
                currentType = property.PropertyType;
            }
            return t;
        }
    }
}

Отвечает ли это на ваш вопрос? Как динамически указать аргумент Linq OrderBy?

jjxtra 18.12.2020 19:05

Извините, я не понимаю, почему вы тестируете поведение OrderBy? Этот метод взят из .net и проверен ими. Или ваш продукт будет сортировать записи ViewModel? В этом случае вам нужно будет вызвать некоторый API, который сортирует ViewModel и проверяет результат в тесте.

Piyush Parashar 18.12.2020 19:06

Ваш тест, похоже, показывает, что OrderBy работает, если только Assert не выбрасывают...

Heretic Monkey 18.12.2020 19:07

Если бы порядок был таким же, Asserts должен был бы быть ` Assert.Equal("02", result[0].Product.Reference); Assert.Equal("03", результат[1].Product.Reference); Assert.Equal("01", результат[2].Product.Reference); Assert.Equal("04", результат[3].Product.Reference); `

Heretic Monkey 18.12.2020 19:10

чтобы было ясно, я тестирую не Order by, а метод PathToProperty. На самом деле тест был просто демонстрацией проблемы.

Mark Johnson 18.12.2020 21:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш PathToProperty неверен. Подумайте о возвращаемом значении — в последний раз вы устанавливаете t = property, а затем возвращаете t. Но property — это PropertyInfo, так что вы просто сравниваете идентичные объекты в OrderBy.

У меня есть аналогичный метод расширения, который я использую:

public static object GetPropertyPathValue(this object curObject, string propsPath) {
    foreach (var propName in propsPath.Split('.'))
        curObject = curObject.GetType().GetProperty(propName).GetValue(curObject);

    return curObject;
}

Если использовать вместо вашего метода PathToProperty, OrderBy будет работать.

var query = model.OrderViewModels.OrderBy(t => t.GetPropertyPathValue("Product.Reference"));

Вы можете обновить свой метод, чтобы он выглядел примерно так:

private static object PathToProperty(object curObject, string path) {
    foreach (string propertyName in path.Split('.')) {
        var property = curObject.GetType().GetProperty(propertyName);
        curObject = property.GetValue(curObject);
    }
    return curObject;
}

для того же результата.

PS На самом деле, используя некоторые другие методы расширения и LINQ, мой обычный метод обрабатывает свойства или поля:

public static object GetPathValue(this object curObject, string memberPath)
    => memberPath.Split('.').Aggregate(curObject, (curObject, memberName) => curObject.GetType().GetPropertyOrField(memberName).GetValue(curObject));

Это идеально, спасибо. В конце концов я отказался от своей версии и использовал ваш метод расширения.

Mark Johnson 19.12.2020 11:45

Другие вопросы по теме