Как получить список свойств с заданным атрибутом?
У меня есть тип t
, и я хотел бы получить список общедоступных свойств, имеющих атрибут MyAttribute
. Атрибут помечен AllowMultiple = false
, например:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
В настоящее время у меня есть это, но я думаю, что есть лучший способ:
foreach (PropertyInfo prop in t.GetProperties())
{
object[] attributes = prop.GetCustomAttributes(typeof(MyAttribute), true);
if (attributes.Length == 1)
{
//Property with my custom attribute
}
}
Как я могу улучшить это? Мои извинения, если это дубликат, есть тонна потоков отражения... кажется, это довольно горячая тема.
Ответы
Ответ 1
var props = t.GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(MyAttribute)));
Это позволяет избежать необходимости материализовывать любые экземпляры атрибутов (т.е. дешевле, чем GetCustomAttribute[s]()
.
Ответ 2
Решение, в конечном итоге использующее большинство, основано на ответе Томаса Петричека. Я обычно хочу что-то делать с атрибутом и свойством.
var props = from p in this.GetType().GetProperties()
let attr = p.GetCustomAttributes(typeof(MyAttribute), true)
where attr.Length == 1
select new { Property = p, Attribute = attr.First() as MyAttribute};
Ответ 3
Насколько я знаю, нет лучшего способа работать с библиотекой Reflection более разумно. Однако вы можете использовать LINQ, чтобы сделать код немного приятнее:
var props = from p in t.GetProperties()
let attrs = p.GetCustomAttributes(typeof(MyAttribute), true)
where attrs.Length != 0 select p;
// Do something with the properties in 'props'
Я считаю, что это поможет вам структурировать код более читаемым образом.
Ответ 4
Всегда есть LINQ:
t.GetProperties().Where(
p=>p.GetCustomAttributes(typeof(MyAttribute), true).Length != 0)
Ответ 5
Если вы регулярно общаетесь с Атрибутами в Reflection, очень важно определить некоторые методы расширения. Вы увидите это во многих проектах. Это один из тех, что я часто имею:
public static bool HasAttribute<T>(this ICustomAttributeProvider provider) where T : Attribute
{
var atts = provider.GetCustomAttributes(typeof(T), true);
return atts.Length > 0;
}
который вы можете использовать как typeof(Foo).HasAttribute<BarAttribute>();
Другие проекты (например, StructureMap) имеют полноценные классы ReflectionHelper, которые используют деревья выражений, чтобы иметь точный синтаксис для идентификации, например. PropertyInfos. Использование тогда выглядит следующим образом:
ReflectionHelper.GetProperty<Foo>(x => x.MyProperty).HasAttribute<BarAttribute>()
Ответ 6
лучший способ:
//if (attributes.Length == 1)
if (attributes.Length != 0)