c# - 如何对列表进行排序通过具有可选属性顺序的对象中的属性
问题描述
假设我有一个基类和两个派生类。
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)
假设这是正确的顺序。
现在,由于在两个派生类中,有一个定义的自定义属性将标识行为应按以下顺序排序的属性顺序:
- ID
- 国家
- 姓名
- 描述
- 数量
- 所有者
- 添加日期
- 其他
因此,将发生的事情CustomAttr[(Order = n)]
应该放在他们的财产秩序中,对于那些没有的人,我们假设他们处于适当的秩序中。Bar
如果我使用该类,这也应该具有类似的行为。
这个用例是我需要List<T>
在 excel 文件中具有正确的类属性顺序才能具有正确的列顺序。
我所做的是我必须添加CustomAttr[(Order = n)]
到所有属性以对它们进行排序,但是这是一件乏味的事情,如果您尝试更改其中一个属性顺序,则需要更改所有属性的顺序。
我有什么办法可以做到这一点?
解决方案
您可以使用反射按照声明的顺序读取类的所有属性的名称。然后,您可以在逻辑中详细说明这一点并相应地对字段进行排序。
尝试以下操作:
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
,根据您的需要,根据字段的声明顺序和顺序对字段进行排序。
但我想这有点超出我的回答范围(它旨在向您展示如何获取属性声明的顺序,从基类到任何给定的特定类)。
推荐阅读
- visual-studio - 在没有 CI/CD 的情况下在 Azure 中运行 Selenium 单元测试?
- java - 如何使用 Java 在 Eclipse 中使用 Checkbox 检索数据
- debugging - VS 代码调试:附加到 process-id 时,是否可以提供 process-id 'pgrep -x "$myprog"' 以在 launch.json(变量“processId”)中使用?
- r - 为什么在 R 编程中只在数字后面使用 L 以使其成为整数?为什么没有其他字母?
- c - 有人可以帮我弄清楚为什么这个简单的功能不起作用吗?
- node.js - 如何将 SHA-256 值设置为 crypto.Hash?
- python - 在“mysql-connector-python”中创建/关闭游标是否对 MySql 有任何作用?
- vue.js - 如何从 vue 中的 shadow dom 访问文档/窗口?
- powershell - 我可以使用 powershell 在 AWS S3 中更新 Zip 文件吗?
- azure-pipelines-build-task - 未找到 Azure 构建 Sql Dacpac