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

C# 如何获取具有给定属性的属性列表?,c#,.net,reflection,C#,.net,Reflection,我有一个类型,t,我想获得具有属性MyAttribute的公共属性列表。该属性标记为AllowMultiple=false,如下所示: [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 目前我所拥有的是这个,但我认为有一个更好的方法: foreach (PropertyInfo prop in t.GetProperties()) { object[] attributes = prop.GetCust

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

我该如何改进这一点?很抱歉,如果这是重复的,那么有大量的反射线程……似乎这是一个非常热门的话题。

据我所知,没有更好的方法可以更智能地使用反射库。但是,您可以使用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)

如果您定期处理反射中的属性,那么定义一些扩展方法是非常非常实用的。你会在很多项目中看到这一点。这是我经常看到的一个:

public static bool HasAttribute<T>(this ICustomAttributeProvider provider) where T : Attribute
{
  var atts = provider.GetCustomAttributes(typeof(T), true);
  return atts.Length > 0;
}
publicstaticboolhasaAttribute(此ICustomAttributeProvider提供程序),其中T:Attribute
{
var atts=provider.GetCustomAttributes(typeof(T),true);
返回附件长度>0;
}
您可以像
typeof(Foo).HasAttribute()一样使用它

其他项目(如StructureMap)具有成熟的ReflectionHelper类,这些类使用表达式树具有良好的语法来标识,如PropertyInfo。用法如下所示:

ReflectionHelper.GetProperty<Foo>(x => x.MyProperty).HasAttribute<BarAttribute>()
ReflectionHelper.GetProperty(x=>x.MyProperty).HasAttribute()

这避免了必须具体化任何属性实例(即,它比
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};

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

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

dotnetfiddle上的示例:

没有。在确定属性是否具有属性之前,您需要一个PropertyInfo。这是一个很好的建议。不过,我需要属性实例,但我喜欢它。我只是想找到一种方法来检查属性的存在,而不必调用属性。谢谢Marc,它很有效!@ÖrjanJämte即使在使用
GetCustomAttributes
时,也不会调用属性
get
;但是,属性是实例化的,这不是免费的。如果不需要检查属性的特定值,
是定义的
更便宜。在4.5中,有一些方法可以检查实例化数据而不实际创建任何数据属性实例(尽管这仅适用于非常特定的场景)@bjhuffine for dotnet core:var props=t.GetProperties()。其中(e=>e.IsDefined(typeof(MyAttribute));+1-“我通常想对属性和属性都做些事情”这就是我想要的-非常感谢您发布您的答案!@cogumel0首先,当然
.Any()
不检查长度。但我的答案不是关于找到的属性只有一个属性。其次,我不确定您是否正确阅读了代码-
。对
GetCustomAttrubutes
方法的结果调用的任何
方法。因此
属性WithMyAttribute
的类型将是pro的集合查看dotnetfiddle上的示例(我添加了答案的链接)。您可以将.Where替换为.Any,因为.Any也允许lambdas。
propertiesWithMyAttribute = type.GetProperties()
  .Where(x => x.GetCustomAttributes(typeof(MyAttribute), true).Any());