首页 > 解决方案 > 如何对列表进行排序通过具有可选属性顺序的对象中的属性

问题描述

假设我有一个基类和两个派生类。

public abstract class BaseClass 
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public string Owner { get; set; }

    public DateTime DateAdded { get; set; }
}

public class Foo : BaseClass
{
    [CustomAttr(Order = 2)]
    public string Country { get; set; }

    [CustomAttr(Order = 5)]
    public decimal Amount { get; set; }

    public string Other { get; set; }
}

public class Bar : BaseClass
{
    [CustomAttr(Order = 3)]
    public string Organization { get; set; }

    [CustomAttr(Order = 1)]
    public string Keywords { get; set; }
}

默认情况下,属性的顺序取决于它们在类中的声明方式,因此如果在其中BaseClass,则没有[CustomAttr(Order = n)假设这是正确的顺序。

现在,由于在两个派生类中,有一个定义的自定义属性将标识行为应按以下顺序排序的属性顺序:

  1. ID
  2. 国家
  3. 姓名
  4. 描述
  5. 数量
  6. 所有者
  7. 添加日期
  8. 其他

因此,将发生的事情CustomAttr[(Order = n)]应该放在他们的财产秩序中,对于那些没有的人,我们假设他们处于适当的秩序中。Bar如果我使用该类,这也应该具有类似的行为。

这个用例是我需要List<T>在 excel 文件中具有正确的类属性顺序才能具有正确的列顺序。

我所做的是我必须添加CustomAttr[(Order = n)]到所有属性以对它们进行排序,但是这是一件乏味的事情,如果您尝试更改其中一个属性顺序,则需要更改所有属性的顺序。

我有什么办法可以做到这一点?

标签: c#listsortinggenerics

解决方案


您可以使用反射按照声明的顺序读取类的所有属性的名称。然后,您可以在逻辑中详细说明这一点并相应地对字段进行排序。

尝试以下操作:

PropertyInfo[] propertyInfos = typeof(Bar).GetProperties();
foreach (var propInfo in propertyInfos)
    Console.WriteLine(propInfo.Name);

这将写入Bar类中的所有属性(这只是一个示例,您可以将其替换为您的任何类),包括从其超类 ( BaseClass) 继承的属性。预期输出:

Organization
Keywords
Id
Name
Description
Owner
DateAdded

请注意,此方法首先列出类中的属性,然后在列出每个超类的层次结构中上升(这就是为什么Bar' 的成员在 ' 的成员之前列出的原因BaseClass)。您可以进一步详细说明代码以根据需要更改顺序。

下面的(未优化的)代码首先创建了所有给定类层次结构的列表,从基类开始到给定T类。之后,它遍历每个类,只发现每个类中定义的属性(我向GetProperties()方法传递了一个参数,说明我只想要公共实例/非静态的属性,并在特定的我目前正在咨询的课程)。

private static void ListAllOrderedPropertiesOfType(Type targetType)
{
    // Generate a list containing the whole hierarchy of classes, from the base type to the type T
    var typesList = new List<Type>();
    for (Type t = targetType; t != typeof(Object); t = t.BaseType)
        typesList.Insert(0, t);

    // Iterate from the base type to type T, printing the properties defined for each of the types
    foreach (Type t in typesList)
    {
        PropertyInfo[] propertyInfos = t.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        foreach (var propInfo in propertyInfos)
            Console.WriteLine(propInfo.Name);
    }
}

所以如果你想知道 type 的所有属性Bar,从最顶层的基类到Bar类,你可以这样调用这个方法:

ListAllOrderedPropertiesOfType(typeof(Bar));

预期的输出将是按以下顺序排列的属性:

Id
Name
Description
Owner
DateAdded
Organization
Keywords

这样您就知道字段的声明顺序及其自定义顺序(通过您的CustomAttr属性)。您现在可以实现排序方法CustomAttr,根据您的需要,根据字段的声明顺序和顺序对字段进行排序。

但我想这有点超出我的回答范围(它旨在向您展示如何获取属性声明的顺序,从基类到任何给定的特定类)。


推荐阅读