Как получить список свойств с заданным атрибутом? - PullRequest
193 голосов
/ 17 февраля 2010

У меня есть тип, 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
    }
}

Как я могу улучшить это? Приношу свои извинения, если это дубликат, существует множество тем для размышлений ... кажется, что это очень горячая тема.

Ответы [ 7 ]

355 голосов
/ 17 февраля 2010
var props = t.GetProperties().Where(
                prop => Attribute.IsDefined(prop, typeof(MyAttribute)));

Это позволяет избежать материализации любых экземпляров атрибута (т. Е. Это дешевле, чем GetCustomAttribute[s]().

41 голосов
/ 09 марта 2011

Решение, которое я использую чаще всего, основано на ответе Томаса Петричека. Я обычно хочу что-то сделать с и атрибутом и свойством.

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};
32 голосов
/ 17 февраля 2010

Насколько я знаю, лучшего способа работы с библиотекой 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'

Я считаю, что это поможет вам структурировать код более читабельным образом.

13 голосов
/ 17 февраля 2010

Всегда есть LINQ:

t.GetProperties().Where(
    p=>p.GetCustomAttributes(typeof(MyAttribute), true).Length != 0)
5 голосов
/ 17 февраля 2010

Если вы регулярно имеете дело с Атрибутами в 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>()
2 голосов
/ 17 января 2018

В дополнение к предыдущим ответам: лучше использовать метод Any() вместо проверки длины коллекции:

propertiesWithMyAttribute = type.GetProperties()
  .Where(x => x.GetCustomAttributes(typeof(MyAttribute), true).Any());

Пример в dotnetfiddle: https://dotnetfiddle.net/96mKep

0 голосов
/ 17 февраля 2010

лучший способ:

//if (attributes.Length == 1)
if (attributes.Length != 0)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...