GetProperties() 顺序不一致(.NET Core 2 和 .NET Core 3)

GetProperties() order is not consistent (.NET Core 2 & .NET Core 3)

我使用反射来获取 class 的 属性 列表。我需要以与代码中声明的顺序完全相同的顺序获取名称。

当我只调用 typeof(TypeOfClass).GetProperties() 时,我得到了有序的属性。

我的项目中添加的一些代码产生了一些反射读取,阻碍了我的构建。

花了一些时间才找到它,但几个小时后,我发现你得到一个 属性 的名字 GetProperty("name") 它可以在进一步调用 [=14 时更改顺序=]

这是重现相同问题的代码(控制台应用程序):

class Program
    {
        private class SomeClass
        {
            public int IntProperty { get; set; }
            public string StringProperty { get; set; }
            public DateTime DateProperty { get; set; }

        }
        static void Main(string[] args)
        {
            PropertyInfo[] propertyInfos = typeof(SomeClass).GetProperties();
            Console.WriteLine(string.Join(", ",propertyInfos.Select(p => p.Name)));
            //Output: IntProperty, StringProperty, DateProperty
        }
    }

GetProperties

之前访问 GetProperty 的相同代码
class Program
    {
        private class SomeClass
        {
            public int IntProperty { get; set; }
            public string StringProperty { get; set; }
            public DateTime DateProperty { get; set; }

        }

        static void Main(string[] args)
        {
            PropertyInfo dateProp = typeof(SomeClass).GetProperty("DateProperty");

            PropertyInfo[] propertyInfos = typeof(SomeClass).GetProperties();
            Console.WriteLine(string.Join(", ",propertyInfos.Select(p => p.Name)));
            //Output: DateProperty, IntProperty, StringProperty
        }
    }

如果执行第二个代码块,它将return以DateProperty作为第一个索引的属性!?

有谁知道为什么,有没有办法确保 GetProperties 总是return相同顺序的相同列表?

PS:我只在 .netcore 3.1 上尝试过。我认为这可能不是以前版本中的错误。

谢谢

简答:你不能。 As stated in the documentation:

The GetProperties method does not return properties in a particular order, such as alphabetical or declaration order. Your code must not depend on the order in which properties are returned, because that order varies.

返回属性的顺序被视为实现细节,您不能依赖该顺序。

要确定属性在源代码中的定义顺序,您需要访问源代码。

您可以使用CallerLineNumberAttribute Class 它允许您获取调用该方法的源文件中的行号。只有在这种情况下,您才能确定属性的顺序。这对我有用:

 private class SomeClass
 {
    [Order]
    public int IntProperty { get; set; }

    [Order]
    public string StringProperty { get; set; }

    [Order]
    public DateTime DateProperty { get; set; }

   }

这将使编译器将顺序插入到您的属性中:

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
 public sealed class OrderAttribute : Attribute
 {
    private readonly int order_;
    public OrderAttribute([CallerLineNumber]int order = 0)
    {
       order_ = order;
    }

    public int Order { get { return order_; } }
  }

PropertyInfo dateProp = typeof(SomeClass).GetProperty("DateProperty");

var propertyInfos = from property in typeof(SomeClass).GetProperties()
                                where Attribute.IsDefined(property, 
                                typeof(OrderAttribute))
                                orderby ((OrderAttribute)property
                                   .GetCustomAttributes(typeof(OrderAttribute), false)
                                    .Single()).Order
                                select property;



Console.WriteLine(string.Join(", ", propertyInfos.Select(p => p.Name)));