本文讲述了C#反射属性顺序!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:
我正在使用https://stackoverflow.com/a/531388/528131中的代码从基础成功检索对象实例的所有属性,问题是派生类型的属性首先被迭代。 由于协议的性质,我首先需要基本属性。
1 2 3 4 | x | y | B z | w | A |
B和A是类,B是从A派生的。x,y,z是B的属性,w是A的属性
这是A.GetProperties(); 正在返回。 我需要这个代替:
1 2 3 4 | w | A x | y | B z | |
有什么方法可以准确地按顺序获得字段吗?
类型中的字段不是"有序的"。这些方法中项目的顺序是实现细节,强烈建议不要依赖它们。
您应该自己订购这些项目,并期望它们可以从任何位置开始,以确保您的程序健壮而不是脆弱。
由于可以要求每个属性提供声明它的类型,因此您可以从头开始创建一个查找,该查找为层次结构中的每个类提供一个编号,从您开始的类型一直到object,通过遍历BaseType Type的属性,并按每个属性的声明类型的查找值进行排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public static IEnumerable<PropertyInfo> GetOrderedProperties(Type type) { Dictionary<Type, int> lookup = new Dictionary<Type, int>(); int count = 0; lookup[type] = count++; Type parent = type.BaseType; while (parent != null) { lookup[parent] = count; count++; parent = parent.BaseType; } return type.GetProperties() .OrderByDescending(prop => lookup[prop.DeclaringType]); } |
反射子系统的文档说,您不能依赖于元素返回的顺序。
也就是说,根据我的经验,在源文件中按声明顺序返回元素是我的经验。在Mono或.NET的将来版本中,这可能是正确的,也可能不是。
尽管如此,如果您希望继续进行操作,最好的选择是使用BindingFlags.DeclaredOnly选项并手动遍历继承层次结构(在子类型之前扫描基本类型以使其顺序正确)。您应该以这样一种方式编写代码,即从单个声明的类型开始的属性排序无关紧要(例如,按名称对它们进行排序);如果.NET框架的行为发生变化,这将使您的代码更加健壮。
Fasterflect这样做(主要是为了能够滤除已被覆盖的虚拟属性)。它还具有帮助程序,可以使用其自己的功能更强大的Flags选择器参数来获取是否经过过滤的属性。
如果单个类型中元素的顺序并不重要,则可以使用以下方法获得列表(使用Fasterflect):
1 | var properties = type.Properties().Reverse().ToList(); |
您应注意,以这种方式反映时(通过遍历并仅获取声明的属性)将多次包含重写的属性。 Fasterflect提供了从结果中过滤掉这些的选项:
1 | var properties = type.Properties( Flags.InstancePublic | Flags.ExcludeBackingMembers ).Reverse().ToList(); |
如果您不希望依赖库,那么该代码是开源的,因此您可以选择所需的位。遍历算法可以在此处看到(第443行)。
您要做的就是通过声明类型分组并反转列表
1 2 3 4 5 | var publicProperties = typeof(T).GetProperties() .GroupBy(p => p.DeclaringType) .Reverse() .SelectMany(g => g) .ToArray(); |
作为另一种排序方法:
1 2 3 4 5 6 7 8 9 10 | PropertyInfo[] properties = type.GetProperties(...); Array.Sort(properties, (pi1, pi2) => { if (pi1.DeclaringType.IsSubclassOf(pi2.DeclaringType)) return 1; else if (pi2.DeclaringType.IsSubclassOf(pi1.DeclaringType)) return -1; else return 0; }); |
您可以从PropertyInfo实例获取声明类型,并按其与object的距离进行排序。
这就是我要做的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | void Main() { typeof(B).GetProperties() .Select((x,i) => new { Prop = x, DeclareOrder = i, InheritanceOrder = GetDepth(x.DeclaringType), }) .OrderByDescending(x => x.InheritanceOrder) .ThenBy(x => x.DeclareOrder) .Dump(); } public class A { public string W {get; set;} } public class B : A { public string X {get; set;} public string Y {get; set;} public string Z {get; set;} } static int GetDepth(Type t) { int depth = 0; while (t != null) { depth++; t = t.BaseType; } return depth; } |
更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。
想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!