我有一个类型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
    }
}

我该如何改进呢?如果这是一个副本,我很抱歉,有大量的反射线程在那里…看起来这是个很热门的话题。


当前回答

除了前面的答案:最好使用方法Any()而不是检查集合的长度:

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

dotnetfiddle的例子:https://dotnetfiddle.net/96mKep

其他回答

var props = t.GetProperties().Where(
                prop => Attribute.IsDefined(prop, typeof(MyAttribute)));

这避免了必须物化任何属性实例(即它比GetCustomAttribute[s]()更便宜。

我最终使用最多的解决方案是基于Tomas Petricek的答案。我通常想同时使用属性和属性。

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};

据我所知,没有比使用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'

我相信这可以帮助您以更易读的方式构建代码。

总是有LINQ:

t.GetProperties().Where(
    p=>p.GetCustomAttributes(typeof(MyAttribute), true).Length != 0)

除了前面的答案:最好使用方法Any()而不是检查集合的长度:

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

dotnetfiddle的例子:https://dotnetfiddle.net/96mKep