Добавьте информацию к атрибуту о заказе, затем вы можете использовать ее для обеспечения заказа, например:
[Writeable(Order = 1)]
Так для следующего атрибута:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class WriteableAttribute : Attribute
{
public int Order { get; set; }
}
Вы можетеполучить упорядоченный выбор свойств следующим образом:
private readonly List<PropertyInfo> _props;
protected Foo()
{
_props = new List<PropertyInfo>();
var props = new Dictionary<int, PropertyInfo>();
foreach (PropertyInfo p in GetType().GetProperties())
{
if (Attribute.IsDefined(p, typeof(WriteableAttribute)))
{
var attr = (WriteableAttribute)p
.GetCustomAttributes(typeof(WriteableAttribute))[0];
props.Add(attr.Order, p);
}
}
_props.AddRange(props.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value));
}
NB Для производственного кода я бы рекомендовал кэшировать информацию о свойствах (например, для каждого типа), поскольку при переносе это будет относительно медленнымдля каждого экземпляра.
Обновление - Кэширование
С некоторыми примерами кэширования поиска и упорядочения свойств:
public static class PropertyReflector
{
private static readonly object SyncObj = new object();
private static readonly Dictionary<Type, List<PropertyInfo>> PropLookup =
new Dictionary<Type, List<PropertyInfo>>();
public static IList<PropertyInfo> GetWritableProperties(Type type)
{
lock (SyncObj)
{
List<PropertyInfo> props;
if (!PropLookup.TryGetValue(type, out props))
{
var propsOrder = new Dictionary<int, PropertyInfo>();
foreach (PropertyInfo p in type.GetProperties())
{
if (Attribute.IsDefined(p, typeof(WriteableAttribute)))
{
var attr = (WriteableAttribute)p.GetCustomAttributes(
typeof(WriteableAttribute), inherit: true)[0];
propsOrder.Add(attr.Order, p);
}
}
props = new List<PropertyInfo>(propsOrder
.OrderBy(kvp => kvp.Key)
.Select(kvp => kvp.Value));
PropLookup.Add(type, props);
}
return props;
}
}
}
Обновление -Нет Linq
Вы можете заменить раздел Linq следующим кодом, чтобы упорядочить свойства и добавить их в кэш:
List<int> order = new List<int>(propsOrder.Keys);
order.Sort();
props = new List<PropertyInfo>();
order.ForEach(i => props.Add(propsOrder[i]));
PropLookup.Add(type, props);
Обновление - Полный Linq
И с использованием полностью решения Linq:
static IList<PropertyInfo> GetWritableProperties(Type type)
{
lock (SyncObj)
{
List<PropertyInfo> props;
if (!PropLookup.TryGetValue(type, out props))
{
props = type.GetProperties()
.Select(p => new { p, Atts = p.GetCustomAttributes(typeof(WriteableAttribute), inherit: true) })
.Where(p => p.Atts.Length != 0)
.OrderBy(p => ((WriteableAttribute)p.Atts[0]).Order)
.Select(p => p.p)
.ToList();
PropLookup.Add(type, props);
}
return props;
}
}