如何获取具有给定属性的属性列表?

wsa*_*lle 201 .net c# reflection

我有一个类型,t我想获得具有该属性的公共属性列表MyAttribute.该属性标有AllowMultiple = false,如下所示:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
Run Code Online (Sandbox Code Playgroud)

目前我拥有的是这个,但我认为有更好的方法:

foreach (PropertyInfo prop in t.GetProperties())
{
    object[] attributes = prop.GetCustomAttributes(typeof(MyAttribute), true);
    if (attributes.Length == 1)
    {
         //Property with my custom attribute
    }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能改善这个?我很抱歉,如果这是重复的,那里有大量的反思线程......似乎这是一个非常热门的话题.

Mar*_*ell 372

var props = t.GetProperties().Where(
                prop => Attribute.IsDefined(prop, typeof(MyAttribute)));
Run Code Online (Sandbox Code Playgroud)

这避免了必须实现任何属性实例(即它比它便宜GetCustomAttribute[s]().

  • @ÖrjanJämte 即使使用“GetCustomAttributes”,属性“get”也不会被调用;然而,该属性是*实例化*的,它不是免费的。如果您不需要检查属性的具体值,则“IsDefined”更便宜。在 4.5 中,有多种方法可以检查实例化数据,而无需实际创建任何属性实例(尽管这仅适用于非常特定的场景) (2认同)
  • @bjhuffine http://msdn.microsoft.com/en-us/library/system.reflection.memberinfo.getcustomattributesdata(v=vs.110).aspx (2认同)
  • 对于 dotnet 核心:var props = t.GetProperties().Where(e => e.IsDefined(typeof(MyAttribute))); (2认同)

wsa*_*lle 42

我最终使用的解决方案基于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};
Run Code Online (Sandbox Code Playgroud)


Tom*_*cek 33

据我所知,在以更智能的方式使用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'
Run Code Online (Sandbox Code Playgroud)

我相信这有助于您以更易读的方式构建代码.


P D*_*ddy 13

LINQ总是:

t.GetProperties().Where(
    p=>p.GetCustomAttributes(typeof(MyAttribute), true).Length != 0)
Run Code Online (Sandbox Code Playgroud)


flq*_*flq 6

如果定期处理反射中的属性,定义一些扩展方法是非常非常实际的.你会在许多项目中看到它.这里有一个我经常有的:

public static bool HasAttribute<T>(this ICustomAttributeProvider provider) where T : Attribute
{
  var atts = provider.GetCustomAttributes(typeof(T), true);
  return atts.Length > 0;
}
Run Code Online (Sandbox Code Playgroud)

你可以使用它 typeof(Foo).HasAttribute<BarAttribute>();

其他项目(例如StructureMap)具有完整的ReflectionHelper类,这些类使用表达式树来具有良好的语法来识别例如PropertyInfos.用法然后看起来像:

ReflectionHelper.GetProperty<Foo>(x => x.MyProperty).HasAttribute<BarAttribute>()
Run Code Online (Sandbox Code Playgroud)