短版
Type.GetProperties的MSDN文档指出,它返回的集合不一定是按字母顺序或声明顺序排列的,尽管运行一个简单的测试表明它通常是按声明顺序返回的。是否有您所知道的特定情况,而不是这样的情况?除此之外,建议的替代方案是什么?
详细版本
我实现了用于Type.GetProperties状态的MSDN文档:
GetProperties方法不按特定顺序返回属性,例如字母顺序或声明顺序。您的代码不能依赖于返回属性的顺序,因为顺序是不同的。
因此,无法保证方法返回的集合将以任何特定方式排序。根据一些测试,我发现相反地,返回的属性是按照它们在类型中定义的顺序显示的。
示例:
class Simple
{
public int FieldB { get; set; }
public string FieldA { get; set; }
public byte FieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Simple Properties:");
foreach (var propInfo in typeof(Simple).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}输出:
Simple Properties:
FieldB
FieldA
FieldC这种情况仅略有不同的一种情况是,当所涉类型的父类也具有属性时:
class Parent
{
public int ParentFieldB { get; set; }
public string ParentFieldA { get; set; }
public byte ParentFieldC { get; set; }
}
class Child : Parent
{
public int ChildFieldB { get; set; }
public string ChildFieldA { get; set; }
public byte ChildFieldC { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Parent Properties:");
foreach (var propInfo in typeof(Parent).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
Console.WriteLine("Child Properties:");
foreach (var propInfo in typeof(Child).GetProperties())
Console.WriteLine("\t{0}", propInfo.Name);
}
}输出:
Parent Properties:
ParentFieldB
ParentFieldA
ParentFieldC
Child Properties:
ChildFieldB
ChildFieldA
ChildFieldC
ParentFieldB
ParentFieldA
ParentFieldC这意味着当发现属性时,GetProperties方法从下向上遍历继承链。这很好,可以按这样的方式处理。
问题:
一个看似显而易见的解决方案是定义一个自定义属性,该属性指示属性应该显示的顺序(类似于DataMember属性上的DataMember属性)。类似于:
public class PropOrderAttribute : Attribute
{
public int SeqNbr { get; set; }
}然后实施如下:
class Simple
{
[PropOrder(SeqNbr = 0)]
public int FieldB { get; set; }
[PropOrder(SeqNbr = 1)]
public string FieldA { get; set; }
[PropOrder(SeqNbr = 2)]
public byte FieldC { get; set; }
}但正如许多人所发现的,如果您的类型有100个属性,并且需要在前两个属性之间添加一个属性,则这将成为一个严重的维护问题。
更新
这里所示的例子只是为了说明而已。在我的特定场景中,我使用类定义消息格式,然后遍历类的属性并获取它们的属性,以查看消息中的特定字段应该如何删除。消息中字段的顺序是重要的,所以我类中属性的顺序需要是重要的。
它目前的工作方式只是迭代来自GetProperties的返回集合,但是由于文档声明不建议我了解为什么以及我还有什么其他选项?
发布于 2012-01-15 18:37:08
命令没有得到保证,无论发生什么..。时有发生。
明显的情况是,这种情况可能发生变化:
但更微妙的情况是:部分类。如果一个类被拆分为多个文件,则它们的使用顺序根本没有定义。请参阅跨部分类的“文本顺序”是否正式定义?
当然,即使对单个(非部分)定义也没有定义;p
但想象一下
档案1
partial class Foo {
public int A {get;set;}
}档案2
partial class Foo {
public int B {get;set:}
}但是,在A和B之间没有正式的声明顺序,请参见链接的帖子,看看它是如何发生的。
重新编辑;最好的方法是分别指定封送处理信息;一种常见的方法是使用接受数字顺序的自定义属性,并使用该属性来修饰成员。然后,您可以根据这个数字订购。protobuf做了一些非常类似的事情,坦率地说,我建议在这里使用一个现有的序列化库:
[ProtoMember(n)]
public int Foo {get;set;}其中"n“是整数。具体来说,在protobuf的情况下,也有一个API分别指定这些数字,当类型不在您的直接控制之下时,这个API非常有用。
发布于 2015-07-06 18:37:57
不管它的价值是什么,按MetadataToken分类似乎对我有用。
GetType().GetProperties().OrderBy(x => x.MetadataToken)原始文章(链接断裂,此处列出原因):http://www.sebastienmahe.com/v3/seb.blog/2010/03/08/c-reflection-getproperties-kept-in-declaration-order/
发布于 2014-05-28 18:36:42
我使用自定义属性来自己添加必要的元数据(它与REST类似的服务一起使用并返回CRLF分隔的Key=Value对)。
首先,一个自定义属性:
class ParameterOrderAttribute : Attribute
{
public int Order { get; private set; }
public ParameterOrderAttribute(int order)
{
Order = order;
}
}然后,装饰你的课程:
class Response : Message
{
[ParameterOrder(0)]
public int Code { get; set; }
}
class RegionsResponse : Response
{
[ParameterOrder(1)]
public string Regions { get; set; }
}
class HousesResponse : Response
{
public string Houses { get; set; }
}将PropertyInfo转换为可排序int的简便方法:
private int PropertyOrder(PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}更好的是,写是作为一个扩展:
static class PropertyInfoExtensions
{
private static int PropertyOrder(this PropertyInfo propInfo)
{
int output;
var orderAttr = (ParameterOrderAttribute)propInfo.GetCustomAttributes(typeof(ParameterOrderAttribute), true).SingleOrDefault();
output = orderAttr != null ? orderAttr.Order : Int32.MaxValue;
return output;
}
}最后,您现在可以使用以下方法查询Type对象:
var props = from p in type.GetProperties()
where p.CanWrite
orderby p.PropertyOrder() ascending
select p;https://stackoverflow.com/questions/8872254
复制相似问题