web-dev-qa-db-ja.com

特定の属性を持つプロパティのリストを取得する方法は?

タイプ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び申し上げます。大量のリフレクションスレッドがそこにあります...非常にホットなトピックのようです。

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

これにより、属性インスタンスを具体化する必要がなくなります(つまり、GetCustomAttribute[s]()よりも安価です)。

363
Marc Gravell

私が最もよく使う解決策は、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};
42
wsanville

私の知る限り、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'

これは、コードをより読みやすい方法で構造化するのに役立つと思います。

33
Tomas Petricek

常にLINQがあります。

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

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>()
5
flq

以前の回答に加えて、コレクションの長さをチェックする代わりに、メソッドAny()を使用することをお勧めします。

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

Dotnetfiddleの例: https://dotnetfiddle.net/96mKep

2
feeeper