С# 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
Почему в Python есть оператор &quot;pass&quot;?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
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

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