Мне нужно использовать строку с разделителями в порядке. ЭГ "Товар.Справочник".
Кажется, у меня проблемы, так как результат упорядочивается так же, как и до вызова метода.
Например, у меня есть этот тест 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;
}
}
}
Извините, я не понимаю, почему вы тестируете поведение OrderBy
? Этот метод взят из .net и проверен ими. Или ваш продукт будет сортировать записи ViewModel? В этом случае вам нужно будет вызвать некоторый API, который сортирует ViewModel и проверяет результат в тесте.
Ваш тест, похоже, показывает, что OrderBy
работает, если только Assert
не выбрасывают...
Если бы порядок был таким же, Assert
s должен был бы быть ` 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); `
чтобы было ясно, я тестирую не Order by, а метод PathToProperty. На самом деле тест был просто демонстрацией проблемы.
Ваш 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));
Это идеально, спасибо. В конце концов я отказался от своей версии и использовал ваш метод расширения.
Отвечает ли это на ваш вопрос? Как динамически указать аргумент Linq OrderBy?