我需要按照在类中声明的顺序使用反射来获取所有属性。根据MSDN的规定,在使用GetProperties()
时无法保证订单。
GetProperties方法不按特定顺序返回属性,如字母顺序或声明顺序。
但我已经了解到,通过按MetadataToken
对属性进行排序可以解决此问题。所以我的问题是,这安全吗?我似乎在MSDN上找不到任何关于它的信息。或者,有没有其他方法来解决这个问题?
我当前的实现如下所示:
var props = typeof(T)
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.OrderBy(x => x.MetadataToken);
发布于 2013-08-01 15:31:00
在.net 4.5 (and even .net 4.0 in vs2012)上,使用[CallerLineNumber]
属性的巧妙技巧可以更好地处理反射,让编译器为您的属性插入顺序:
[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; }
}
然后使用反射:
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]
对属性进行额外的排序。
发布于 2012-01-30 13:02:12
如果你使用属性路由,这是我在过去用过的方法;
public static IOrderedEnumerable<PropertyInfo> GetSortedProperties<T>()
{
return typeof(T)
.GetProperties()
.OrderBy(p => ((Order)p.GetCustomAttributes(typeof(Order), false)[0]).Order);
}
然后像这样使用它;
var test = new TestRecord { A = 1, B = 2, C = 3 };
foreach (var prop in GetSortedProperties<TestRecord>())
{
Console.WriteLine(prop.GetValue(test, null));
}
在哪里;
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的帖子的链接中有一个很好的示例。
发布于 2012-01-30 11:03:37
根据MSDN的说法,MetadataToken
在一个模块中是独一无二的-没有任何东西说它可以保证任何顺序。
即使它确实按照您希望的方式运行,这也是特定于实现的,并且可以在没有通知的情况下随时更改。
看看这个旧的MSDN blog entry。
我强烈建议远离对这些实现细节的任何依赖--参见this answer from Marc Gravell。
如果您在编译时需要一些东西,可以看看Roslyn (尽管它还处于非常早期的阶段)。
https://stackoverflow.com/questions/9062235
复制相似问题