首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使用反射按声明顺序获取属性

使用反射按声明顺序获取属性
EN

Stack Overflow用户
提问于 2012-01-30 10:09:48
回答 10查看 43.3K关注 0票数 94

我需要按照在类中声明的顺序使用反射来获取所有属性。根据MSDN的规定,在使用GetProperties()时无法保证订单。

GetProperties方法不按特定顺序返回属性,如字母顺序或声明顺序。

但我已经了解到,通过按MetadataToken对属性进行排序可以解决此问题。所以我的问题是,这安全吗?我似乎在MSDN上找不到任何关于它的信息。或者,有没有其他方法来解决这个问题?

我当前的实现如下所示:

代码语言:javascript
运行
AI代码解释
复制
var props = typeof(T)
   .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
   .OrderBy(x => x.MetadataToken);
EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2013-08-01 15:31:00

在.net 4.5 (and even .net 4.0 in vs2012)上,使用[CallerLineNumber]属性的巧妙技巧可以更好地处理反射,让编译器为您的属性插入顺序:

代码语言:javascript
运行
AI代码解释
复制
[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_; } }
}


public class Test
{
    //This sets order_ field to current line number
    [Order]
    public int Property2 { get; set; }

    //This sets order_ field to current line number
    [Order]
    public int Property1 { get; set; }
}

然后使用反射:

代码语言:javascript
运行
AI代码解释
复制
var properties = from property in typeof(Test).GetProperties()
                 where Attribute.IsDefined(property, typeof(OrderAttribute))
                 orderby ((OrderAttribute)property
                           .GetCustomAttributes(typeof(OrderAttribute), false)
                           .Single()).Order
                 select property;

foreach (var property in properties)
{
   //
}

如果你必须处理分部类,你可以使用[CallerFilePath]对属性进行额外的排序。

票数 168
EN

Stack Overflow用户

发布于 2012-01-30 13:02:12

如果你使用属性路由,这是我在过去用过的方法;

代码语言:javascript
运行
AI代码解释
复制
public static IOrderedEnumerable<PropertyInfo> GetSortedProperties<T>()
{
  return typeof(T)
    .GetProperties()
    .OrderBy(p => ((Order)p.GetCustomAttributes(typeof(Order), false)[0]).Order);
}

然后像这样使用它;

代码语言:javascript
运行
AI代码解释
复制
var test = new TestRecord { A = 1, B = 2, C = 3 };

foreach (var prop in GetSortedProperties<TestRecord>())
{
    Console.WriteLine(prop.GetValue(test, null));
}

在哪里;

代码语言:javascript
运行
AI代码解释
复制
class TestRecord
{
    [Order(1)]
    public int A { get; set; }

    [Order(2)]
    public int B { get; set; }

    [Order(3)]
    public int C { get; set; }
}

显然,如果在所有属性上没有可比较的属性的类型上运行该方法,那么该方法将会反胃,所以要小心它的使用方式,并且它应该足以满足需求。

我省略了Order : Attribute的定义,因为Yahia到Marc Gravell的帖子的链接中有一个很好的示例。

票数 17
EN

Stack Overflow用户

发布于 2012-01-30 11:03:37

根据MSDN的说法,MetadataToken在一个模块中是独一无二的-没有任何东西说它可以保证任何顺序。

即使它确实按照您希望的方式运行,这也是特定于实现的,并且可以在没有通知的情况下随时更改。

看看这个旧的MSDN blog entry

我强烈建议远离对这些实现细节的任何依赖--参见this answer from Marc Gravell

如果您在编译时需要一些东西,可以看看Roslyn (尽管它还处于非常早期的阶段)。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9062235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档