首页 > 解决方案 > C# Linq OrderBy 反射与 . 分隔字符串

问题描述

我需要按顺序使用分隔字符串。EG“产品。参考”。

我似乎遇到了麻烦,因为结果的排序方式与调用该方法之前的方式相同。

例如,我有这个 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;
        }
    }
}

标签: c#linqreflection

解决方案


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));

推荐阅读