【问题标题】:GetProperties() order is not consistent (.NET Core 2 & .NET Core 3)GetProperties() 顺序不一致(.NET Core 2 和 .NET Core 3)
【发布时间】:2020-06-01 19:38:38
【问题描述】:

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

当我只打电话给typeof(TypeOfClass).GetProperties() 时,我得到了良好的属性。

在我的项目中添加的一些代码产生了一些影响我构建的反射读取。

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

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

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
        }
    }

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

有人知道为什么吗,有没有办法确保 GetProperties 总是以相同的顺序返回相同的列表?

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

谢谢

【问题讨论】:

  • 仅供参考:.Net Framework 4.7 没有问题,只是测试过......问题也存在于 .Net Core 2.0 中

标签: .net-core c#-8.0


【解决方案1】:

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

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

【讨论】:

  • 谢谢,不知道 CallerLineNumberAttribute 编译属性,我猜要适度使用..
【解决方案2】:

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

GetProperties 方法不按特定顺序返回属性,例如字母顺序或声明顺序。您的代码不得依赖于返回属性的顺序,因为该顺序会有所不同。

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

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

【讨论】:

  • 感谢您指出文档。我知道这不是使用代码/声明顺序的最佳实践,但是......,赞成但采用了属性的解决方案,因为我生成了一个动态 SqlBulkCopy 数据读取器,它需要/要求以相同的顺序排列列(流式传输需要)。再次感谢您。
猜你喜欢
  • 2020-03-20
  • 2019-12-28
  • 1970-01-01
  • 2020-08-10
  • 1970-01-01
  • 2018-02-07
  • 2020-02-01
  • 2019-12-09
  • 1970-01-01
相关资源
最近更新 更多