タイプ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
}
}
これを改善するにはどうすればよいですか?これが重複している場合はおologiesび申し上げます。大量のリフレクションスレッドがそこにあります...非常にホットなトピックのようです。
var props = t.GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(MyAttribute)));
これにより、属性インスタンスを具体化する必要がなくなります(つまり、GetCustomAttribute[s]()
よりも安価です)。
私が最もよく使う解決策は、Tomas Petricekの答えに基づいています。私は通常both属性とプロパティで何かをしたいです。
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)
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など)には、Expressionツリーを使用して、たとえばPropertyInfos。使用方法は次のようになります。
ReflectionHelper.GetProperty<Foo>(x => x.MyProperty).HasAttribute<BarAttribute>()
以前の回答に加えて、コレクションの長さをチェックする代わりに、メソッドAny()
を使用することをお勧めします。
propertiesWithMyAttribute = type.GetProperties()
.Where(x => x.GetCustomAttributes(typeof(MyAttribute), true).Any());
Dotnetfiddleの例: https://dotnetfiddle.net/96mKep